forked from quic-go/quic-go
jsontext: add support for encoding null (#5371)
This commit is contained in:
@@ -19,6 +19,7 @@ const (
|
|||||||
kindUint
|
kindUint
|
||||||
kindFloat
|
kindFloat
|
||||||
kindBool
|
kindBool
|
||||||
|
kindNull
|
||||||
kindObjectStart
|
kindObjectStart
|
||||||
kindObjectEnd
|
kindObjectEnd
|
||||||
kindArrayStart
|
kindArrayStart
|
||||||
@@ -60,6 +61,9 @@ func Bool(b bool) Token {
|
|||||||
return Token{kind: kindBool, b: b}
|
return Token{kind: kindBool, b: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Null is a null token.
|
||||||
|
var Null Token = Token{kind: kindNull}
|
||||||
|
|
||||||
// BeginObject is the begin object token.
|
// BeginObject is the begin object token.
|
||||||
var BeginObject Token = Token{kind: kindObjectStart}
|
var BeginObject Token = Token{kind: kindObjectStart}
|
||||||
|
|
||||||
@@ -86,6 +90,7 @@ var (
|
|||||||
colonByte = []byte(":")
|
colonByte = []byte(":")
|
||||||
trueByte = []byte("true")
|
trueByte = []byte("true")
|
||||||
falseByte = []byte("false")
|
falseByte = []byte("false")
|
||||||
|
nullByte = []byte("null")
|
||||||
openObjectByte = []byte("{")
|
openObjectByte = []byte("{")
|
||||||
closeObjectByte = []byte("}")
|
closeObjectByte = []byte("}")
|
||||||
openArrayByte = []byte("[")
|
openArrayByte = []byte("[")
|
||||||
@@ -256,6 +261,11 @@ func (e *Encoder) WriteToken(t Token) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.afterValue()
|
e.afterValue()
|
||||||
|
case kindNull:
|
||||||
|
if _, err = e.w.Write(nullByte); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.afterValue()
|
||||||
case kindObjectStart:
|
case kindObjectStart:
|
||||||
if _, err = e.w.Write(openObjectByte); err != nil {
|
if _, err = e.w.Write(openObjectByte); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ func TestEncoderNumbersAndBool(t *testing.T) {
|
|||||||
enc.WriteToken(jsontext.True)
|
enc.WriteToken(jsontext.True)
|
||||||
enc.WriteToken(jsontext.String("false"))
|
enc.WriteToken(jsontext.String("false"))
|
||||||
enc.WriteToken(jsontext.False)
|
enc.WriteToken(jsontext.False)
|
||||||
|
enc.WriteToken(jsontext.String("nullv"))
|
||||||
|
enc.WriteToken(jsontext.Null)
|
||||||
enc.WriteToken(jsontext.EndObject)
|
enc.WriteToken(jsontext.EndObject)
|
||||||
output := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
@@ -99,6 +101,7 @@ func TestEncoderNumbersAndBool(t *testing.T) {
|
|||||||
"float": 3.14,
|
"float": 3.14,
|
||||||
"true": true,
|
"true": true,
|
||||||
"false": false,
|
"false": false,
|
||||||
|
"nullv": nil,
|
||||||
}, got)
|
}, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +129,21 @@ func TestEncoderEmptyArray(t *testing.T) {
|
|||||||
require.Equal(t, []any{}, got)
|
require.Equal(t, []any{}, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEncoderArrayWithNulls(t *testing.T) {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
enc := jsontext.NewEncoder(buf)
|
||||||
|
enc.WriteToken(jsontext.BeginArray)
|
||||||
|
enc.WriteToken(jsontext.Null)
|
||||||
|
enc.WriteToken(jsontext.String("x"))
|
||||||
|
enc.WriteToken(jsontext.Null)
|
||||||
|
enc.WriteToken(jsontext.EndArray)
|
||||||
|
output := buf.String()
|
||||||
|
|
||||||
|
var got []any
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(output), &got))
|
||||||
|
require.Equal(t, []any{nil, "x", nil}, got)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEncoderEscapedStrings(t *testing.T) {
|
func TestEncoderEscapedStrings(t *testing.T) {
|
||||||
t.Run("no escapes", func(t *testing.T) {
|
t.Run("no escapes", func(t *testing.T) {
|
||||||
testEncoderEscapedStrings(t, "simplekey", "simplevalue")
|
testEncoderEscapedStrings(t, "simplekey", "simplevalue")
|
||||||
@@ -210,6 +228,9 @@ func encodeValue(t testing.TB, enc *jsontext.Encoder, v any) (isSupported bool)
|
|||||||
case bool:
|
case bool:
|
||||||
require.NoError(t, enc.WriteToken(jsontext.Bool(val)))
|
require.NoError(t, enc.WriteToken(jsontext.Bool(val)))
|
||||||
return true
|
return true
|
||||||
|
case nil:
|
||||||
|
require.NoError(t, enc.WriteToken(jsontext.Null))
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -326,12 +347,13 @@ func FuzzEncoder(f *testing.F) {
|
|||||||
examples := []string{
|
examples := []string{
|
||||||
`{"hello": "world"}`,
|
`{"hello": "world"}`,
|
||||||
`{"foo": 123, "bar": [1, 2, 3]}`,
|
`{"foo": 123, "bar": [1, 2, 3]}`,
|
||||||
`{"nested": {"a": 1, "b": [true, false, "foobar"]}}`,
|
`{"nested": {"a": 1, "b": [true, false, "foobar", null]}}`,
|
||||||
`[{"x": 1}, {"y": "foo"}]`,
|
`[{"x": 1}, {"y": "foo"}]`,
|
||||||
`["foo", "bar"]`,
|
`["foo", "bar"]`,
|
||||||
`["a", {"b": [1, 2, {"c": "d"}]}, 3]`,
|
`["a", {"b": [1, 2, {"c": "d"}]}, 3]`,
|
||||||
`{"emptyObj": {}, "emptyArr": []}`,
|
`{"emptyObj": {}, "emptyArr": []}`,
|
||||||
`{"mixed": [1, "two", {"three": 3}]}`,
|
`{"mixed": [1, "two", {"three": 3}]}`,
|
||||||
|
`[null]`,
|
||||||
}
|
}
|
||||||
for _, tc := range examples {
|
for _, tc := range examples {
|
||||||
// first test that
|
// first test that
|
||||||
|
|||||||
Reference in New Issue
Block a user