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)
|
assertErr(t, err)
|
||||||
assertEq(t, "[]interface{}", `[1,2.1,"hello"]`, string(bytes))
|
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) {
|
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-]"
|
result := "[\n-\t1,\n-\t2.1,\n-\t\"hello\"\n-]"
|
||||||
assertEq(t, "[]interface{}", result, string(bytes))
|
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) {
|
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)
|
b = appendComma(ctx, bb)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpSlicePtr:
|
case encoder.OpSlicePtr:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag & encoder.NilSliceAsEmptyOption != 0
|
||||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
fallthrough
|
fallthrough
|
||||||
case encoder.OpSlice:
|
case encoder.OpSlice:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag & encoder.NilSliceAsEmptyOption != 0
|
||||||
p := load(ctxptr, code.Idx)
|
p := load(ctxptr, code.Idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || slice.Data == nil {
|
if p == 0 || slice.Data == nil {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OptionFlag uint8
|
type OptionFlag uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
HTMLEscapeOption OptionFlag = 1 << iota
|
HTMLEscapeOption OptionFlag = 1 << iota
|
||||||
IndentOption
|
IndentOption
|
||||||
UnorderedMapOption
|
UnorderedMapOption
|
||||||
|
NilSliceAsEmptyOption
|
||||||
DebugOption
|
DebugOption
|
||||||
ColorizeOption
|
ColorizeOption
|
||||||
ContextOption
|
ContextOption
|
||||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
b = appendComma(ctx, bb)
|
b = appendComma(ctx, bb)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpSlicePtr:
|
case encoder.OpSlicePtr:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
fallthrough
|
fallthrough
|
||||||
case encoder.OpSlice:
|
case encoder.OpSlice:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := load(ctxptr, code.Idx)
|
p := load(ctxptr, code.Idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || slice.Data == nil {
|
if p == 0 || slice.Data == nil {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
b = appendComma(ctx, bb)
|
b = appendComma(ctx, bb)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpSlicePtr:
|
case encoder.OpSlicePtr:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
fallthrough
|
fallthrough
|
||||||
case encoder.OpSlice:
|
case encoder.OpSlice:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := load(ctxptr, code.Idx)
|
p := load(ctxptr, code.Idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || slice.Data == nil {
|
if p == 0 || slice.Data == nil {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
b = appendComma(ctx, bb)
|
b = appendComma(ctx, bb)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpSlicePtr:
|
case encoder.OpSlicePtr:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
fallthrough
|
fallthrough
|
||||||
case encoder.OpSlice:
|
case encoder.OpSlice:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := load(ctxptr, code.Idx)
|
p := load(ctxptr, code.Idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || slice.Data == nil {
|
if p == 0 || slice.Data == nil {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,19 +301,29 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
b = appendComma(ctx, bb)
|
b = appendComma(ctx, bb)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
case encoder.OpSlicePtr:
|
case encoder.OpSlicePtr:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
|
||||||
if p == 0 {
|
if p == 0 {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
store(ctxptr, code.Idx, p)
|
store(ctxptr, code.Idx, p)
|
||||||
fallthrough
|
fallthrough
|
||||||
case encoder.OpSlice:
|
case encoder.OpSlice:
|
||||||
|
nilSliceAsEmpty := ctx.Option.Flag&encoder.NilSliceAsEmptyOption != 0
|
||||||
p := load(ctxptr, code.Idx)
|
p := load(ctxptr, code.Idx)
|
||||||
slice := ptrToSlice(p)
|
slice := ptrToSlice(p)
|
||||||
if p == 0 || slice.Data == nil {
|
if p == 0 || slice.Data == nil {
|
||||||
|
if nilSliceAsEmpty {
|
||||||
|
b = appendEmptyArray(ctx, b)
|
||||||
|
} else {
|
||||||
b = appendNullComma(ctx, b)
|
b = appendNullComma(ctx, b)
|
||||||
|
}
|
||||||
code = code.End.Next
|
code = code.End.Next
|
||||||
break
|
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.
|
// DisableHTMLEscape disables escaping of HTML characters ( '&', '<', '>' ) when encoding string.
|
||||||
func DisableHTMLEscape() EncodeOptionFunc {
|
func DisableHTMLEscape() EncodeOptionFunc {
|
||||||
return func(opt *EncodeOption) {
|
return func(opt *EncodeOption) {
|
||||||
|
|
Loading…
Reference in New Issue