diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index a28086dc15e2..56933dd0bbef 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -33,9 +33,11 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ## [Unreleased] -## [v0.13.7](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.7) - 2024-12-16 +## [v0.13.8](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.8) - 2025-01-28 -### Bug Fixes +* [#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. + +## [v0.13.7](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.7) - 2024-12-16 * Fix [ABS-0043](https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-8wcc-m6j2-qxvm) Limit recursion depth for unknown field detection diff --git a/x/tx/signing/aminojson/json_marshal.go b/x/tx/signing/aminojson/json_marshal.go index 1e5d1b59af81..338ea9d88a61 100644 --- a/x/tx/signing/aminojson/json_marshal.go +++ b/x/tx/signing/aminojson/json_marshal.go @@ -38,6 +38,8 @@ type EncoderOptions struct { // It is useful when using the Amino JSON encoder for non Amino purposes, // such as JSON RPC. AminoNameAsTypeURL bool + // MarshalMappings when set will use the Amino JSON encoder to marshal maps. + MarshalMappings bool // TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages. TypeResolver signing.TypeResolver // FileResolver is used to resolve protobuf file descriptors TypeURL when TypeResolver fails. @@ -57,6 +59,7 @@ type Encoder struct { indent string enumsAsString bool aminoNameAsTypeURL bool + marshalMappings bool } // 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 { indent: options.Indent, enumsAsString: options.EnumAsString, aminoNameAsTypeURL: options.AminoNameAsTypeURL, + marshalMappings: options.MarshalMappings, } return enc } @@ -237,6 +241,20 @@ func (enc Encoder) marshal(value protoreflect.Value, fd protoreflect.FieldDescri return err case protoreflect.Map: + if enc.marshalMappings { + if !val.IsValid() { + _, err := io.WriteString(writer, "null") + return err + } + + mapData := make(map[string]interface{}) + val.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { + mapData[k.String()] = v.Interface() + return true + }) + + return jsonMarshal(writer, mapData) + } return errors.New("maps are not supported") case protoreflect.List: diff --git a/x/tx/signing/aminojson/json_marshal_test.go b/x/tx/signing/aminojson/json_marshal_test.go index 29d2f8cf8f59..7dae096f8410 100644 --- a/x/tx/signing/aminojson/json_marshal_test.go +++ b/x/tx/signing/aminojson/json_marshal_test.go @@ -265,7 +265,6 @@ func TestIndent(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "ABitOfEverything", "value": { @@ -324,7 +323,6 @@ func TestEnumAsString(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "ABitOfEverything", "value": { @@ -383,7 +381,6 @@ func TestAminoNameAsTypeURL(t *testing.T) { bz, err := encoder.Marshal(msg) require.NoError(t, err) - fmt.Println(string(bz)) require.Equal(t, `{ "type": "/testpb.ABitOfEverything", "value": { @@ -414,3 +411,29 @@ func TestAminoNameAsTypeURL(t *testing.T) { } }`, string(bz)) } + +func TestMarshalMappings(t *testing.T) { + // valid + encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: true}) + + msg := &testpb.WithAMap{ + StrMap: map[string]string{ + "foo": "bar", + "baz": "qux", + }, + } + + bz, err := encoder.Marshal(msg) + require.NoError(t, err) + require.Equal(t, `{ + "str_map": { + "baz": "qux", + "foo": "bar" + } +}`, string(bz)) + + // invalid + encoder = aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " ", MarshalMappings: false}) + _, err = encoder.Marshal(msg) + require.Error(t, err) +}