gojson: added MarshalSafeCollections

This commit is contained in:
2023-04-20 14:34:57 +02:00
parent d780c7965f
commit ef3705937c
7 changed files with 167 additions and 549 deletions

View File

@@ -167,6 +167,17 @@ func Marshal(v any) ([]byte, error) {
return buf, nil
}
// MarshalSafeCollections is like Marshal except it will marshal nil maps and
// slices as '{}' and '[]' respectfully instead of 'null'
func MarshalSafeCollections(v interface{}, nilSafeSlices bool, nilSafeMaps bool) ([]byte, error) {
e := &encodeState{}
err := e.marshal(v, encOpts{escapeHTML: true, nilSafeSlices: nilSafeSlices, nilSafeMaps: nilSafeMaps})
if err != nil {
return nil, err
}
return e.Bytes(), nil
}
// MarshalIndent is like Marshal but applies Indent to format the output.
// Each JSON element in the output will begin on a new line beginning with prefix
// followed by one or more copies of indent according to the indentation nesting.
@@ -363,6 +374,10 @@ type encOpts struct {
quoted bool
// escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
escapeHTML bool
// nilSafeSlices marshals a nil slices into '[]' instead of 'null'
nilSafeSlices bool
// nilSafeMaps marshals a nil maps '{}' instead of 'null'
nilSafeMaps bool
}
type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
@@ -776,7 +791,11 @@ type mapEncoder struct {
func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
if opts.nilSafeMaps {
e.WriteString("{}")
} else {
e.WriteString("null")
}
return
}
if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
@@ -829,9 +848,13 @@ func newMapEncoder(t reflect.Type) encoderFunc {
return me.encode
}
func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
func encodeByteSlice(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
if opts.nilSafeSlices {
e.WriteString(`""`)
} else {
e.WriteString("null")
}
return
}
s := v.Bytes()
@@ -866,7 +889,11 @@ type sliceEncoder struct {
func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
if opts.nilSafeSlices {
e.WriteString("[]")
} else {
e.WriteString("null")
}
return
}
if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {