Using ArrayEach in concert with Set leads to some weird behavior. Specifically that ArrayEach provides slices over the original json object, such that the capacity of the slice is jsonEnd-(startOffsetOfSlice). This interacts poorly with Set when a particular key does not exist in the object being mutated. Given this testcase, you can see the output shows the second JSON object becoming malformed upon setting a non-existent key in the first object.
func TestWhatHappens(t *testing.T) {
jsonObject := `[{"key1":"Foo","key2":"Bar","key3":"baz"},{"key1":"boo","key2":"dog","key3":"cat","key4":"mouse"}]`
var allSlices [][]byte
_, err := jsonparser.ArrayEach([]byte(jsonObject), func(value []byte, _ jsonparser.ValueType, _ int, err error) {
if err != nil {
t.Fatalf("failed: %s", err)
}
allSlices = append(allSlices, value)
})
if err != nil {
t.Fatalf("failed: %s", err)
}
newVal, err := jsonparser.Set(allSlices[0], []byte(strconv.Quote(`mouse`)), "key4")
if err != nil {
t.Fatalf("failed %s: ", err)
}
fmt.Println(string(newVal))
fmt.Println(string(allSlices[1]))
}
The suggested fix is to change this line:
|
value = append(data[:startOffset], append(createInsertComponent(keys[depth:], setValue, comma, object), data[depthOffset:]...)...) |
to
value = append(data[:startOffset:startOffset], append(createInsertComponent(keys[depth:], setValue, comma, object), data[depthOffset:]...)...)
which truncates the capacity causing append to allocate a new slice. Alternatively, the pattern in the path currently exists flow can be used, this just happened to be a nifty one-liner
Using
ArrayEachin concert withSetleads to some weird behavior. Specifically thatArrayEachprovides slices over the original json object, such that the capacity of the slice isjsonEnd-(startOffsetOfSlice). This interacts poorly withSetwhen a particular key does not exist in the object being mutated. Given this testcase, you can see the output shows the second JSON object becoming malformed upon setting a non-existent key in the first object.The suggested fix is to change this line:
jsonparser/parser.go
Line 794 in f7e751e
to
which truncates the capacity causing
appendto allocate a new slice. Alternatively, the pattern in thepath currently existsflow can be used, this just happened to be a nifty one-liner