mirror of https://github.com/goccy/go-json.git
Add NilSliceAsEmpty encode option
This commit is contained in:
parent
41ad89fe02
commit
4cb0c9b28f
|
@ -426,6 +426,21 @@ func Test_Marshal(t *testing.T) {
|
|||
assertErr(t, err)
|
||||
assertEq(t, "[]interface{}", `[1,2.1,"hello"]`, string(bytes))
|
||||
})
|
||||
t.Run("nil_slice", func(t *testing.T) {
|
||||
var a []int
|
||||
bytes, err := json.Marshal(a)
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice", `null`, string(bytes))
|
||||
bytes, err = json.Marshal(&a)
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice_ptr", `null`, string(bytes))
|
||||
bytes, err = json.MarshalWithOption(a, json.NilSliceAsEmpty())
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice_as_empty", `[]`, string(bytes))
|
||||
bytes, err = json.MarshalWithOption(&a, json.NilSliceAsEmpty())
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice_ptr_as_empty", `[]`, string(bytes))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("array", func(t *testing.T) {
|
||||
|
@ -590,6 +605,15 @@ func Test_MarshalIndent(t *testing.T) {
|
|||
result := "[\n-\t1,\n-\t2.1,\n-\t\"hello\"\n-]"
|
||||
assertEq(t, "[]interface{}", result, string(bytes))
|
||||
})
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var a []int
|
||||
bytes, err := json.MarshalIndent(a, prefix, indent)
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice", `null`, string(bytes))
|
||||
bytes, err = json.MarshalIndentWithOption(a, prefix, indent, json.NilSliceAsEmpty())
|
||||
assertErr(t, err)
|
||||
assertEq(t, "nil_slice_as_empty", `[]`, string(bytes))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("array", func(t *testing.T) {
|
||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
|||
b = appendComma(ctx, bb)
|
||||
code = code.Next
|
||||
case encoder.OpSlicePtr:
|
||||
nilSliceAsEmpty := ctx.Option.Flag & encoder.NilSliceAsEmptyOption != 0
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
if p == 0 {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
fallthrough
|
||||
case encoder.OpSlice:
|
||||
nilSliceAsEmpty := ctx.Option.Flag & encoder.NilSliceAsEmptyOption != 0
|
||||
p := load(ctxptr, code.Idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || slice.Data == nil {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
|
|
|
@ -5,12 +5,13 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
type OptionFlag uint8
|
||||
type OptionFlag uint16
|
||||
|
||||
const (
|
||||
HTMLEscapeOption OptionFlag = 1 << iota
|
||||
IndentOption
|
||||
UnorderedMapOption
|
||||
NilSliceAsEmptyOption
|
||||
DebugOption
|
||||
ColorizeOption
|
||||
ContextOption
|
||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
|||
b = appendComma(ctx, bb)
|
||||
code = code.Next
|
||||
case encoder.OpSlicePtr:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
if p == 0 {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
fallthrough
|
||||
case encoder.OpSlice:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := load(ctxptr, code.Idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || slice.Data == nil {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
|||
b = appendComma(ctx, bb)
|
||||
code = code.Next
|
||||
case encoder.OpSlicePtr:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
if p == 0 {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
fallthrough
|
||||
case encoder.OpSlice:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := load(ctxptr, code.Idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || slice.Data == nil {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
|||
b = appendComma(ctx, bb)
|
||||
code = code.Next
|
||||
case encoder.OpSlicePtr:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
if p == 0 {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
fallthrough
|
||||
case encoder.OpSlice:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := load(ctxptr, code.Idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || slice.Data == nil {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
|||
b = appendComma(ctx, bb)
|
||||
code = code.Next
|
||||
case encoder.OpSlicePtr:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||
if p == 0 {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
store(ctxptr, code.Idx, p)
|
||||
fallthrough
|
||||
case encoder.OpSlice:
|
||||
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||
p := load(ctxptr, code.Idx)
|
||||
slice := ptrToSlice(p)
|
||||
if p == 0 || slice.Data == nil {
|
||||
b = appendNullComma(ctx, b)
|
||||
if nilSliceAsEmpty {
|
||||
b = appendEmptyArray(ctx, b)
|
||||
} else {
|
||||
b = appendNullComma(ctx, b)
|
||||
}
|
||||
code = code.End.Next
|
||||
break
|
||||
}
|
||||
|
|
|
@ -17,6 +17,13 @@ func UnorderedMap() EncodeOptionFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// NilSliceAsEmpty encodes nil slices as [] instead of null.
|
||||
func NilSliceAsEmpty() EncodeOptionFunc {
|
||||
return func(opt *EncodeOption) {
|
||||
opt.Flag |= encoder.NilSliceAsEmptyOption
|
||||
}
|
||||
}
|
||||
|
||||
// DisableHTMLEscape disables escaping of HTML characters ( '&', '<', '>' ) when encoding string.
|
||||
func DisableHTMLEscape() EncodeOptionFunc {
|
||||
return func(opt *EncodeOption) {
|
||||
|
|
Loading…
Reference in New Issue