Description
When decoding JSON data into an existing map object, an existing key's value is reallocated. I can't determine conclusively whether or not this is expected behavior, but the doc seems to be
unclear on this case.
The example below should explain this in a better way:
https://play.golang.org/p/y_VMAgevTNg
It is unexpected that B and A (as variables) lose coherence after the call to json.Unmarshal. The call reallocates "A.B", creating a copy of it. After that call, the objects are independent, which may be unexpected behavior.
What did you expect to see?
1
{"B":5}
{"A":{"B":5}}
2
{"B":6}
{"A":{"B":6}}
3
2009/11/10 23:00:00 addr(A=0x414030 C=0x43e260 C[A]=0x414030)
2009/11/10 23:00:00 addr(A=0x414030 C=0x43e260 C[A]=0x414030)
{"B":7}
{"A":{"B":7}}
4
{"B":16}
{"A":{"B":16}}
What did you see instead?
1
{"B":5}
{"A":{"B":5}}
2
{"B":6}
{"A":{"B":6}}
3
2009/11/10 23:00:00 addr(A=0x414030 C=0x43e260 C[A]=0x414030)
2009/11/10 23:00:00 addr(A=0x414030 C=0x43e260 C[A]=0x414140)
{"B":6}
{"A":{"B":7}}
4
{"B":16}
{"A":{"B":7}}
Possibly relevant godoc from encoding/json
Specifically, this part:
Unmarshal unmarshals the JSON into the value pointed at by the pointer.
To me implies that it does not allocate a new value and set the pointer to point to it, but instead uses the existing value pointed at.
Unmarshal uses the inverse of the encodings that Marshal uses,
allocating maps, slices, and pointers as necessary, with the following
additional rules:
To unmarshal JSON into a pointer, Unmarshal first handles the case of
the JSON being the JSON literal null. In that case, Unmarshal sets the
pointer to nil. Otherwise, Unmarshal unmarshals the JSON into the value
pointed at by the pointer. If the pointer is nil, Unmarshal allocates a
new value for it to point to.
To unmarshal a JSON object into a map, Unmarshal first establishes a map
to use. If the map is nil, Unmarshal allocates a new map. Otherwise
Unmarshal reuses the existing map, keeping existing entries. Unmarshal
then stores key-value pairs from the JSON object into the map. The map's
key type must either be a string, an integer, or implement
encoding.TextUnmarshaler.