go icon indicating copy to clipboard operation
go copied to clipboard

Incorrect indention when marshaling map/object

Open creekwax opened this issue 4 years ago • 0 comments

There are some cases jsoniter behaves incorrectly when marshaling map/object with indention.

  1. Nested map/obj/slice inside map encoding using sortedKeysMapEncoder have incorrect indentions.
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
    // ...
    subStream := stream.cfg.BorrowStream(nil)
    subStream.Attachment = stream.Attachment
    // ...
    stream.cfg.ReturnStream(subStream)
}

The stream borrowed from sync.Pool always has 0 initial indention and returned with 0 indention. So when processing nested elements if SortMapKeys: true is configured inside the Config, the encoding will always have a single unit of indention step. eg.

var json = jsoniter.ConfigCompatibleWithStandardLibrary
var obj interface{}
var x []byte

obj = map[int]map[int]int{1: {1: 2}}
x, _ = json.MarshalIndent(obj, "", "    ")
fmt.Println(string(x))

obj = map[int]map[int]int{1: {1: 2}}
x, _ = json.MarshalIndent(obj, "", "    ")
fmt.Println(string(x))

obj = map[int]struct{ F int }{1: {F: 2}}
x, _ = json.MarshalIndent(obj, "", "    ")
fmt.Println(string(x))

Results:

{
    "1": [
    1,
    2
]
}
{
    "1": {
    "1": 2
}
}
{
    "1": {
    "F": 2
}
}

Expects:

{
    "1": [
        1,
        2
    ]
}
{
    "1": {
        "1": 2
    }
}
{
    "1": {
        "F": 2
    }
}
  1. Empty map or object with no fields to be marshaled has redundant indention introduced by (*Stream).WriteObjectStart.
    • Empty map is not recognized as an empty object to be written by a Stream.
    • Object that all fields with omitempty tag will have redundant indention if these exported fields are all empty.
var json = jsoniter.ConfigCompatibleWithStandardLibrary
var obj interface{}
var x []byte

obj = map[int]int{}
x, _ = json.MarshalIndent(obj, "", "    ")
fmt.Println(string(x))

obj = struct {
     Empty int `json:"empty,omitempty"`
}{}
x, _ = json.MarshalIndent(obj, "", "    ")
fmt.Println(string(x))

Results:

{

}
{

}

Expects:

{}
{}

creekwax avatar Aug 17 '21 04:08 creekwax