Add NilSliceAsEmpty encode option

This commit is contained in:
w1ck3dg0ph3r 2022-09-01 10:42:38 +04:00
parent 41ad89fe02
commit 4cb0c9b28f
No known key found for this signature in database
GPG Key ID: 508376B17E6F5DEB
8 changed files with 93 additions and 11 deletions

View File

@ -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) {

View File

@ -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
}

View File

@ -5,12 +5,13 @@ import (
"io"
)
type OptionFlag uint8
type OptionFlag uint16
const (
HTMLEscapeOption OptionFlag = 1 << iota
IndentOption
UnorderedMapOption
NilSliceAsEmptyOption
DebugOption
ColorizeOption
ContextOption

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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) {