Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ func (m Map) JSON() (string, error) {
}

func cleanUpInterfaceArray(in []interface{}) []interface{} {
if in == nil {
return nil
}
result := make([]interface{}, len(in))
for i, v := range in {
result[i] = cleanUp(v)
Expand All @@ -68,6 +71,9 @@ func cleanUpInterfaceArray(in []interface{}) []interface{} {
}

func cleanUpInterfaceMap(in map[interface{}]interface{}) Map {
if in == nil {
return nil
}
result := Map{}
for k, v := range in {
result[fmt.Sprintf("%v", k)] = cleanUp(v)
Expand All @@ -76,6 +82,9 @@ func cleanUpInterfaceMap(in map[interface{}]interface{}) Map {
}

func cleanUpStringMap(in map[string]interface{}) Map {
if in == nil {
return nil
}
result := Map{}
for k, v := range in {
result[k] = cleanUp(v)
Expand All @@ -84,6 +93,9 @@ func cleanUpStringMap(in map[string]interface{}) Map {
}

func cleanUpMSIArray(in []map[string]interface{}) []Map {
if in == nil {
return nil
}
result := make([]Map, len(in))
for i, v := range in {
result[i] = cleanUpStringMap(v)
Expand All @@ -92,6 +104,9 @@ func cleanUpMSIArray(in []map[string]interface{}) []Map {
}

func cleanUpMapArray(in []Map) []Map {
if in == nil {
return nil
}
result := make([]Map, len(in))
for i, v := range in {
result[i] = cleanUpStringMap(v)
Expand Down
62 changes: 62 additions & 0 deletions conversions_nil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package objx_test

import (
"encoding/base64"
"testing"

"github.com/stretchr/objx"
)

func TestConversionJSONPreservesNilContainers(t *testing.T) {
tests := []struct {
name string
value interface{}
json string
}{
{"nil interface slice", []interface{}(nil), "null"},
{"nil map slice", []objx.Map(nil), "null"},
{"nil string map slice", []map[string]interface{}(nil), "null"},
{"nil map", objx.Map(nil), "null"},
{"nil interface map", map[interface{}]interface{}(nil), "null"},
{"nil string map", map[string]interface{}(nil), "null"},
{"nil string slice", []string(nil), "null"},
{"nil interface", nil, "null"},
{"empty interface slice", []interface{}{}, "[]"},
{"empty map slice", []objx.Map{}, "[]"},
{"empty string map slice", []map[string]interface{}{}, "[]"},
{"empty map", objx.Map{}, "{}"},
{"empty interface map", map[interface{}]interface{}{}, "{}"},
{"populated interface slice", []interface{}{1}, "[1]"},
{"populated map slice", []objx.Map{{"key": "value"}}, `[{"key":"value"}]`},
{"populated string map slice", []map[string]interface{}{{"key": "value"}}, `[{"key":"value"}]`},
{"populated map", objx.Map{"key": "value"}, `{"key":"value"}`},
{"populated interface map", map[interface{}]interface{}{1: "value"}, `{"1":"value"}`},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we t.Parralell() these tests?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added t.Parallel() to the table cases and captured the loop variable for Go 1.20/1.21. The full suite and five shuffled race-detector runs pass on Windows.

t.Parallel()
for _, context := range []struct {
name string
input objx.Map
want string
}{
{"direct", objx.Map{"value": test.value}, `{"value":` + test.json + `}`},
{"in slice", objx.Map{"value": []interface{}{test.value}}, `{"value":[` + test.json + `]}`},
{"in map", objx.Map{"value": objx.Map{"nested": test.value}}, `{"value":{"nested":` + test.json + `}}`},
} {
t.Run(context.name, func(t *testing.T) {
got, err := context.input.JSON()
require.NoError(t, err)
assert.Equal(t, context.want, got)
assert.Equal(t, context.want, context.input.MustJSON())
encoded, err := context.input.Base64()
require.NoError(t, err)
decoded, err := base64.StdEncoding.DecodeString(encoded)
require.NoError(t, err)
assert.Equal(t, context.want, string(decoded))
})
}
})
}
}