Skip to content

Commit

Permalink
codec: json: allow parsing non-string scalars where a string is expected
Browse files Browse the repository at this point in the history
This allows us to parse valid json non-strings i.e. null, true, false or numbers
into a string correctly.

Also added TestJsonDecodeNonStringScalarInStringContext to validate it.

Fixes #202
  • Loading branch information
ugorji committed Aug 26, 2017
1 parent 40b14ef commit 8c0409f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
15 changes: 15 additions & 0 deletions codec/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,21 @@ func TestJsonLargeInteger(t *testing.T) {
}
}

func TestJsonDecodeNonStringScalarInStringContext(t *testing.T) {
var b = `{"s.true": "true", "b.true": true, "s.false": "false", "b.false": false, "s.10": "10", "i.10": 10, "i.-10": -10}`
var golden = map[string]string{"s.true": "true", "b.true": "true", "s.false": "false", "b.false": "false", "s.10": "10", "i.10": "10", "i.-10": "-10"}

var m map[string]string
d := NewDecoderBytes([]byte(b), testJsonH)
d.MustDecode(&m)
if err := deepEqual(golden, m); err == nil {
logT(t, "++++ match: decoded: %#v", m)
} else {
logT(t, "---- mismatch: %v ==> golden: %#v, decoded: %#v", err, golden, m)
failT(t)
}
}

// TODO:
// Add Tests for:
// - decoding empty list/map in stream into a nil slice/map
Expand Down
35 changes: 26 additions & 9 deletions codec/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,9 @@ LOOP:
switch state {
case 0:
state = 2
// do not add sign to the slice ...
if storeBytes {
d.bs = append(d.bs, b)
}
b, eof = r.readn1eof()
continue
case 6: // typ = jsonNumFloat
Expand All @@ -715,7 +717,9 @@ LOOP:
case 0:
state = 2
n.neg = true
// do not add sign to the slice ...
if storeBytes {
d.bs = append(d.bs, b)
}
b, eof = r.readn1eof()
continue
case 6: // typ = jsonNumFloat
Expand Down Expand Up @@ -981,16 +985,28 @@ func (d *jsonDecDriver) appendStringAsBytes() {
d.tok = b
}

// handle null as a string
if d.tok == 'n' {
d.readStrIdx(10, 13) // ull
d.bs = d.bs[:0]
if d.tok != '"' {
// d.d.errorf("json: expect char '%c' but got char '%c'", '"', d.tok)
// handle non-string scalar: null, true, false or a number
switch d.tok {
case 'n':
d.readStrIdx(10, 13) // ull
d.bs = d.bs[:0]
case 'f':
d.readStrIdx(5, 9) // alse
d.bs = d.bs[:5]
copy(d.bs, "false")
case 't':
d.readStrIdx(1, 4) // rue
d.bs = d.bs[:4]
copy(d.bs, "true")
default:
// try to parse a valid number
d.decNum(true)
}
return
}

if d.tok != '"' {
d.d.errorf("json: expect char '%c' but got char '%c'", '"', d.tok)
}
d.tok = 0

v := d.bs[:0]
Expand Down Expand Up @@ -1159,6 +1175,7 @@ func (d *jsonDecDriver) DecodeNaked() {
type JsonHandle struct {
textEncodingType
BasicHandle

// RawBytesExt, if configured, is used to encode and decode raw bytes in a custom way.
// If not configured, raw bytes are encoded to/from base64 text.
RawBytesExt InterfaceExt
Expand Down

0 comments on commit 8c0409f

Please sign in to comment.