Skip to content

Commit 6137389

Browse files
committed
add custom JSON marshaling for DefaultMetadata
1 parent b60355c commit 6137389

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

.changeset/famous-doors-ask.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": patch
3+
---
4+
5+
marshall json without double-encoding

datastore/default_metadata.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
package datastore
22

3+
import "encoding/json"
4+
35
// DefaultMetadata is a struct that can be used as a default metadata type.
46
type DefaultMetadata struct {
57
Data string `json:"data"`
68
}
79

810
// DefaultMetadata implements the Cloneable interface
9-
func (d DefaultMetadata) Clone() DefaultMetadata { return d }
11+
func (dm DefaultMetadata) Clone() DefaultMetadata { return dm }
12+
13+
// MarshalJSON handles both JSON and non-JSON data in the Data field.
14+
// Without custom marshaling, the Data field would be double-encoded if it contains JSON.
15+
func (dm DefaultMetadata) MarshalJSON() ([]byte, error) {
16+
// Try to parse the Data field as JSON first
17+
var jsonData interface{}
18+
err := json.Unmarshal([]byte(dm.Data), &jsonData)
19+
20+
if err == nil {
21+
// It's valid JSON, create a custom map
22+
return json.Marshal(map[string]interface{}{
23+
"data": jsonData,
24+
})
25+
}
26+
27+
// Not valid JSON, use normal marshaling. Alias is used to avoid recursion
28+
type Alias DefaultMetadata
29+
30+
return json.Marshal(Alias(dm))
31+
}

datastore/default_metadata_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package datastore
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestDefaultMetadataMarshalJSON(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
input DefaultMetadata
14+
expected string
15+
}{
16+
{
17+
name: "Supports any string",
18+
input: DefaultMetadata{Data: "basic data"},
19+
expected: `{"data":"basic data"}`,
20+
},
21+
{
22+
name: "Supports JSON object without double encoding",
23+
input: DefaultMetadata{Data: `{"link":1,"name":"satoshi"}`},
24+
expected: `{"data":{"link":1,"name":"satoshi"}}`,
25+
},
26+
{
27+
name: "Valid JSON array",
28+
input: DefaultMetadata{Data: `[1,2,3,4]`},
29+
expected: `{"data":[1,2,3,4]}`,
30+
},
31+
{
32+
name: "Empty string",
33+
input: DefaultMetadata{Data: ""},
34+
expected: `{"data":""}`,
35+
},
36+
{
37+
name: "Invalid JSON",
38+
input: DefaultMetadata{Data: `{admin:"0xdeadbeef"}`},
39+
expected: `{"data":"{admin:\"0xdeadbeef\"}"}`,
40+
},
41+
}
42+
43+
for _, tt := range tests {
44+
t.Run(tt.name, func(t *testing.T) {
45+
result, err := json.Marshal(tt.input)
46+
require.NoError(t, err)
47+
require.NotNil(t, result)
48+
49+
require.Equal(t, tt.expected, string(result), "Expected output does not match")
50+
})
51+
}
52+
}

0 commit comments

Comments
 (0)