Skip to content

Commit 8cb7fa5

Browse files
fix: bugfix for setting JSON keys with special characters
1 parent 99dff1a commit 8cb7fa5

File tree

3 files changed

+9
-9
lines changed

3 files changed

+9
-9
lines changed

internal/apijson/decoder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func (d *decoderBuilder) newUnionDecoder(t reflect.Type) decoderFunc {
224224
}
225225

226226
if len(unionEntry.discriminatorKey) != 0 {
227-
discriminatorValue := n.Get(unionEntry.discriminatorKey).Value()
227+
discriminatorValue := n.Get(EscapeSJSONKey(unionEntry.discriminatorKey)).Value()
228228
if discriminatorValue == variant.DiscriminatorValue {
229229
inner := reflect.New(variant.Type).Elem()
230230
err := decoder(n, inner, state)

internal/apijson/encoder.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import (
1818

1919
var encoders sync.Map // map[encoderEntry]encoderFunc
2020

21+
// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
22+
// special characters that sjson interprets as a path.
23+
var EscapeSJSONKey = strings.NewReplacer("\\", "\\\\", "|", "\\|", "#", "\\#", "@", "\\@", "*", "\\*", ".", "\\.", ":", "\\:", "?", "\\?").Replace
24+
2125
func Marshal(value interface{}) ([]byte, error) {
2226
e := &encoder{dateFormat: time.RFC3339}
2327
return e.marshal(value)
@@ -276,7 +280,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
276280
if encoded == nil {
277281
continue
278282
}
279-
json, err = sjson.SetRawBytes(json, ef.tag.name, encoded)
283+
json, err = sjson.SetRawBytes(json, EscapeSJSONKey(ef.tag.name), encoded)
280284
if err != nil {
281285
return nil, err
282286
}
@@ -354,7 +358,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error)
354358
}
355359
encodedKeyString = string(encodedKeyBytes)
356360
}
357-
encodedKey := []byte(sjsonReplacer.Replace(encodedKeyString))
361+
encodedKey := []byte(encodedKeyString)
358362
pairs = append(pairs, mapPair{key: encodedKey, value: iter.Value()})
359363
}
360364

@@ -372,7 +376,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error)
372376
if len(encodedValue) == 0 {
373377
continue
374378
}
375-
json, err = sjson.SetRawBytes(json, string(p.key), encodedValue)
379+
json, err = sjson.SetRawBytes(json, EscapeSJSONKey(string(p.key)), encodedValue)
376380
if err != nil {
377381
return nil, err
378382
}
@@ -392,7 +396,3 @@ func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc {
392396
return json, nil
393397
}
394398
}
395-
396-
// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
397-
// special characters that sjson interprets as a path.
398-
var sjsonReplacer *strings.Replacer = strings.NewReplacer(".", "\\.", ":", "\\:", "*", "\\*")

internal/apijson/json_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ var tests = map[string]struct {
362362
"date_time_nano_missing_t_coerce": {`"2007-03-01 13:03:05.123456789Z"`, time.Date(2007, time.March, 1, 13, 3, 5, 123456789, time.UTC)},
363363

364364
"map_string": {`{"foo":"bar"}`, map[string]string{"foo": "bar"}},
365-
"map_string_with_sjson_path_chars": {`{":a.b.c*:d*-1e.f":"bar"}`, map[string]string{":a.b.c*:d*-1e.f": "bar"}},
365+
"map_string_with_sjson_path_chars": {`{":a.b.c*:d*-1e.f@g?h":"bar"}`, map[string]string{":a.b.c*:d*-1e.f@g?h": "bar"}},
366366
"map_interface": {`{"a":1,"b":"str","c":false}`, map[string]interface{}{"a": float64(1), "b": "str", "c": false}},
367367

368368
"primitive_struct": {

0 commit comments

Comments
 (0)