Skip to content

Commit

Permalink
Convert json numbers to numbers (#5496)
Browse files Browse the repository at this point in the history
  • Loading branch information
WithoutPants authored Nov 21, 2024
1 parent 5f690d9 commit 6c5bf5f
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
16 changes: 16 additions & 0 deletions internal/api/resolver_mutation_configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"context"
"encoding/json"
"errors"
"fmt"
"path/filepath"
Expand Down Expand Up @@ -643,10 +644,14 @@ func (r *mutationResolver) ConfigureUI(ctx context.Context, input map[string]int
c := config.GetInstance()

if input != nil {
// #5483 - convert JSON numbers to float64 or int64
input = utils.ConvertMapJSONNumbers(input)
c.SetUIConfiguration(input)
}

if partial != nil {
// #5483 - convert JSON numbers to float64 or int64
partial = utils.ConvertMapJSONNumbers(partial)
// merge partial into existing config
existing := c.GetUIConfiguration()
utils.MergeMaps(existing, partial)
Expand All @@ -664,13 +669,24 @@ func (r *mutationResolver) ConfigureUISetting(ctx context.Context, key string, v
c := config.GetInstance()

cfg := utils.NestedMap(c.GetUIConfiguration())

// #5483 - convert JSON numbers to float64 or int64
if m, ok := value.(map[string]interface{}); ok {
value = utils.ConvertMapJSONNumbers(m)
} else if n, ok := value.(json.Number); ok {
value = utils.JSONNumberToNumber(n)
}

cfg.Set(key, value)

return r.ConfigureUI(ctx, cfg, nil)
}

func (r *mutationResolver) ConfigurePlugin(ctx context.Context, pluginID string, input map[string]interface{}) (map[string]interface{}, error) {
c := config.GetInstance()

// #5483 - convert JSON numbers to float64 or int64
input = utils.ConvertMapJSONNumbers(input)
c.SetPluginConfiguration(pluginID, input)

if err := c.Write(); err != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/utils/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package utils

import (
"encoding/json"
"strings"
)

// JSONNumberToNumber converts a JSON number to either a float64 or int64.
func JSONNumberToNumber(n json.Number) interface{} {
if strings.Contains(string(n), ".") {
f, _ := n.Float64()
return f
}
ret, _ := n.Int64()
return ret
}
17 changes: 17 additions & 0 deletions pkg/utils/map.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"encoding/json"
"strings"
)

Expand Down Expand Up @@ -79,3 +80,19 @@ func MergeMaps(dest map[string]interface{}, src map[string]interface{}) {
dest[k] = v
}
}

// ConvertMapJSONNumbers converts all JSON numbers in a map to either float64 or int64.
func ConvertMapJSONNumbers(m map[string]interface{}) (ret map[string]interface{}) {
ret = make(map[string]interface{})
for k, v := range m {
if n, ok := v.(json.Number); ok {
ret[k] = JSONNumberToNumber(n)
} else if mm, ok := v.(map[string]interface{}); ok {
ret[k] = ConvertMapJSONNumbers(mm)
} else {
ret[k] = v
}
}

return ret
}
55 changes: 55 additions & 0 deletions pkg/utils/map_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package utils

import (
"encoding/json"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

func TestNestedMapGet(t *testing.T) {
Expand Down Expand Up @@ -279,3 +282,55 @@ func TestMergeMaps(t *testing.T) {
})
}
}

func TestConvertMapJSONNumbers(t *testing.T) {
tests := []struct {
name string
input map[string]interface{}
expected map[string]interface{}
}{
{
name: "Convert JSON numbers to numbers",
input: map[string]interface{}{
"int": json.Number("12"),
"float": json.Number("12.34"),
"string": "foo",
},
expected: map[string]interface{}{
"int": int64(12),
"float": 12.34,
"string": "foo",
},
},
{
name: "Convert JSON numbers to numbers in nested maps",
input: map[string]interface{}{
"foo": map[string]interface{}{
"int": json.Number("56"),
"float": json.Number("56.78"),
"nested-string": "bar",
},
"int": json.Number("12"),
"float": json.Number("12.34"),
"string": "foo",
},
expected: map[string]interface{}{
"foo": map[string]interface{}{
"int": int64(56),
"float": 56.78,
"nested-string": "bar",
},
"int": int64(12),
"float": 12.34,
"string": "foo",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ConvertMapJSONNumbers(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}

0 comments on commit 6c5bf5f

Please sign in to comment.