Skip to content

Commit f1b139d

Browse files
feat(x/tx): add an option to encode maps using amino json (backport #23539) (#23540)
Co-authored-by: Julien Robert <[email protected]>
1 parent 9d3c384 commit f1b139d

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

x/tx/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos-
3333

3434
## [Unreleased]
3535

36-
## [v0.13.7](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.7) - 2024-12-16
36+
## [v0.13.8](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.8) - 2025-01-28
3737

38-
### Bug Fixes
38+
* [#23513](https://github.com/cosmos/cosmos-sdk/pull/23513), [#23539](https://github.com/cosmos/cosmos-sdk/pull/23539) Add map marshalling support (as option) to Amino JSON encoder.
39+
40+
## [v0.13.7](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.7) - 2024-12-16
3941

4042
* Fix [ABS-0043](https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-8wcc-m6j2-qxvm) Limit recursion depth for unknown field detection
4143

x/tx/signing/aminojson/json_marshal.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ type EncoderOptions struct {
3838
// It is useful when using the Amino JSON encoder for non Amino purposes,
3939
// such as JSON RPC.
4040
AminoNameAsTypeURL bool
41+
// MarshalMappings when set will use the Amino JSON encoder to marshal maps.
42+
MarshalMappings bool
4143
// TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages.
4244
TypeResolver signing.TypeResolver
4345
// FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails.
@@ -57,6 +59,7 @@ type Encoder struct {
5759
indent string
5860
enumsAsString bool
5961
aminoNameAsTypeURL bool
62+
marshalMappings bool
6063
}
6164

6265
// NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding
@@ -93,6 +96,7 @@ func NewEncoder(options EncoderOptions) Encoder {
9396
indent: options.Indent,
9497
enumsAsString: options.EnumAsString,
9598
aminoNameAsTypeURL: options.AminoNameAsTypeURL,
99+
marshalMappings: options.MarshalMappings,
96100
}
97101
return enc
98102
}
@@ -237,6 +241,20 @@ func (enc Encoder) marshal(value protoreflect.Value, fd protoreflect.FieldDescri
237241
return err
238242

239243
case protoreflect.Map:
244+
if enc.marshalMappings {
245+
if !val.IsValid() {
246+
_, err := io.WriteString(writer, "null")
247+
return err
248+
}
249+
250+
mapData := make(map[string]interface{})
251+
val.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
252+
mapData[k.String()] = v.Interface()
253+
return true
254+
})
255+
256+
return jsonMarshal(writer, mapData)
257+
}
240258
return errors.New("maps are not supported")
241259

242260
case protoreflect.List:

x/tx/signing/aminojson/json_marshal_test.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ func TestIndent(t *testing.T) {
265265

266266
bz, err := encoder.Marshal(msg)
267267
require.NoError(t, err)
268-
fmt.Println(string(bz))
269268
require.Equal(t, `{
270269
"type": "ABitOfEverything",
271270
"value": {
@@ -324,7 +323,6 @@ func TestEnumAsString(t *testing.T) {
324323

325324
bz, err := encoder.Marshal(msg)
326325
require.NoError(t, err)
327-
fmt.Println(string(bz))
328326
require.Equal(t, `{
329327
"type": "ABitOfEverything",
330328
"value": {
@@ -383,7 +381,6 @@ func TestAminoNameAsTypeURL(t *testing.T) {
383381

384382
bz, err := encoder.Marshal(msg)
385383
require.NoError(t, err)
386-
fmt.Println(string(bz))
387384
require.Equal(t, `{
388385
"type": "/testpb.ABitOfEverything",
389386
"value": {
@@ -414,3 +411,29 @@ func TestAminoNameAsTypeURL(t *testing.T) {
414411
}
415412
}`, string(bz))
416413
}
414+
415+
func TestMarshalMappings(t *testing.T) {
416+
// valid
417+
encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: true})
418+
419+
msg := &testpb.WithAMap{
420+
StrMap: map[string]string{
421+
"foo": "bar",
422+
"baz": "qux",
423+
},
424+
}
425+
426+
bz, err := encoder.Marshal(msg)
427+
require.NoError(t, err)
428+
require.Equal(t, `{
429+
"str_map": {
430+
"baz": "qux",
431+
"foo": "bar"
432+
}
433+
}`, string(bz))
434+
435+
// invalid
436+
encoder = aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: false})
437+
_, err = encoder.Marshal(msg)
438+
require.Error(t, err)
439+
}

0 commit comments

Comments
 (0)