Skip to content

Commit

Permalink
add prefix option to allow caller for flattern customization
Browse files Browse the repository at this point in the history
Signed-off-by: Leslie Qi Wang <[email protected]>
  • Loading branch information
leslie-qiwa authored and nqd committed Dec 3, 2022
1 parent bf87297 commit 1b37ff8
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 1 deletion.
6 changes: 5 additions & 1 deletion flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
// Options the flatten options.
// By default: Delimiter = "."
type Options struct {
Prefix string
Delimiter string
Safe bool
MaxDepth int
Expand All @@ -27,7 +28,7 @@ func Flatten(nested map[string]interface{}, opts *Options) (m map[string]interfa
}
}

m, err = flatten("", 0, nested, opts)
m, err = flatten(opts.Prefix, 0, nested, opts)

return
}
Expand Down Expand Up @@ -125,6 +126,9 @@ func unflatten(flat map[string]interface{}, opts *Options) (nested map[string]in
func uf(k string, v interface{}, opts *Options) (n interface{}) {
n = v

if opts.Prefix != "" {
k = strings.TrimPrefix(k, opts.Prefix+opts.Delimiter)
}
keys := strings.Split(k, opts.Delimiter)

for i := len(keys) - 1; i >= 0; i-- {
Expand Down
120 changes: 120 additions & 0 deletions flat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,123 @@ func TestUnflatten(t *testing.T) {
}
}
}

func TestFlattenPrefix(t *testing.T) {
tests := []struct {
given string
options *Options
want map[string]interface{}
}{
// test with different primitives
// String: 'world',
// Number: 1234.99,
// Boolean: true,
// null: null,
{
`{"hello": "world"}`,
&Options{Prefix: "test", Delimiter: "."},
map[string]interface{}{"test.hello": "world"},
},
{
`{"hello": 1234.99}`,
&Options{Prefix: "test", Delimiter: "_"},
map[string]interface{}{"test_hello": 1234.99},
},
{
`{"hello": true}`,
&Options{Prefix: "test", Delimiter: "-"},
map[string]interface{}{"test-hello": true},
},
{
`{"hello":{"world":"good morning"}}`,
&Options{Prefix: "test", Delimiter: "."},
map[string]interface{}{"test.hello.world": "good morning"},
},
{
`{"hello":{"world":1234.99}}`,
&Options{Prefix: "test", Delimiter: "_"},
map[string]interface{}{"test_hello_world": 1234.99},
},
{
`{"hello":{"world":true}}`,
&Options{Prefix: "test", Delimiter: "-"},
map[string]interface{}{"test-hello-world": true},
},
}
for i, test := range tests {
var given interface{}
err := json.Unmarshal([]byte(test.given), &given)
if err != nil {
t.Errorf("%d: failed to unmarshal test: %v", i+1, err)
}
got, err := Flatten(given.(map[string]interface{}), test.options)
if err != nil {
t.Errorf("%d: failed to flatten: %v", i+1, err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
}
}
}

func TestUnflattenPrefix(t *testing.T) {
tests := []struct {
flat map[string]interface{}
options *Options
want map[string]interface{}
}{
{
map[string]interface{}{"test.hello": "world"},
&Options{Prefix: "test", Delimiter: "."},
map[string]interface{}{"hello": "world"},
},
{
map[string]interface{}{"test_hello": 1234.56},
&Options{Prefix: "test", Delimiter: "_"},
map[string]interface{}{"hello": 1234.56},
},
{
map[string]interface{}{"test-hello": true},
&Options{Prefix: "test", Delimiter: "-"},
map[string]interface{}{"hello": true},
},
// nested twice
{
map[string]interface{}{"test.hello.world.again": "good morning"},
&Options{Prefix: "test", Delimiter: "."},
map[string]interface{}{
"hello": map[string]interface{}{
"world": map[string]interface{}{
"again": "good morning",
},
},
},
},
// custom delimiter
{
map[string]interface{}{
"test hello world again": "good morning",
},
&Options{
Prefix: "test",
Delimiter: " ",
},
map[string]interface{}{
"hello": map[string]interface{}{
"world": map[string]interface{}{
"again": "good morning",
},
},
},
},
}
for i, test := range tests {
got, err := Unflatten(test.flat, test.options)
if err != nil {
t.Errorf("%d: failed to unflatten: %v", i+1, err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("%d: mismatch, got: %v want: %v", i+1, got, test.want)
}
}
}

0 comments on commit 1b37ff8

Please sign in to comment.