diff options
Diffstat (limited to 'encode.go')
-rw-r--r-- | encode.go | 45 |
1 files changed, 31 insertions, 14 deletions
@@ -385,34 +385,51 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, utf Inval return err } + var kBuf strings.Builder + kEnc := NewReEncoder(&kBuf, ReEncoderConfig{ + AllowMultipleValues: true, + + Compact: true, + + BackslashEscape: escaper, + InvalidUTF8: utf, + }) + type kv struct { - K string - V reflect.Value + KStr string + K reflect.Value + V reflect.Value } kvs := make([]kv, val.Len()) iter := val.MapRange() for i := 0; iter.Next(); i++ { - // TODO: Avoid buffering the map key - var k strings.Builder - if err := encode(NewReEncoder(&k, ReEncoderConfig{BackslashEscape: escaper, InvalidUTF8: utf}), iter.Key(), escaper, utf, false, cycleDepth, cycleSeen); err != nil { + if err := encode(kEnc, iter.Key(), escaper, utf, false, cycleDepth, cycleSeen); err != nil { return err } - kStr := k.String() + if err := kEnc.Close(); err != nil { + return err + } + kStr := strings.Trim(kBuf.String(), "\n") + kBuf.Reset() if kStr == "null" { - kStr = `""` + kStr = "" } - if !strings.HasPrefix(kStr, `"`) { - k.Reset() - if err := jsonstring.EncodeStringFromString(&k, escaper, utf, iter.Key(), kStr); err != nil { + + // TODO(lukeshu): Have kEnc look at the first byte, and feed directly to a decoder, + // instead of needing to buffer the whole thing twice. + if strings.HasPrefix(kStr, `"`) { + if err := DecodeString(strings.NewReader(kStr), &kBuf); err != nil { return err } - kStr = k.String() + kStr = kBuf.String() + kBuf.Reset() } - kvs[i].K = kStr + kvs[i].KStr = kStr + kvs[i].K = iter.Key() kvs[i].V = iter.Value() } sort.Slice(kvs, func(i, j int) bool { - return kvs[i].K < kvs[j].K + return kvs[i].KStr < kvs[j].KStr }) for i, kv := range kvs { @@ -421,7 +438,7 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, utf Inval return err } } - if _, err := w.WriteString(kv.K); err != nil { + if err := jsonstring.EncodeStringFromString(w, escaper, utf, kv.K, kv.KStr); err != nil { return err } if err := w.WriteByte(':'); err != nil { |