Skip to content

Commit

Permalink
feat(x/tx): add indent option to encoder (#17600)
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt authored Sep 11, 2023
1 parent 152ec92 commit 91fad07
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
7 changes: 7 additions & 0 deletions x/tx/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

## v0.10.0

### Features

* [#17600](https://github.com/cosmos/cosmos-sdk/pull/17600) Add encoder `DefineScalarEncoding` method for defining custom scalar encodings.
* [#17600](https://github.com/cosmos/cosmos-sdk/pull/17600) Add indent option to encoder.

## v0.9.1

### Improvements
Expand Down
33 changes: 32 additions & 1 deletion x/tx/signing/aminojson/json_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ type FieldEncoder func(*Encoder, protoreflect.Value, io.Writer) error

// EncoderOptions are options for creating a new Encoder.
type EncoderOptions struct {
// DonotSortFields when set turns off sorting of field names.
// Indent can only be composed of space or tab characters.
// It defines the indentation used for each level of indentation.
Indent string
// DoNotSortFields when set turns off sorting of field names.
DoNotSortFields bool
// TypeResolver is used to resolve protobuf message types by TypeURL when marshaling any packed messages.
TypeResolver signing.TypeResolver
Expand All @@ -40,6 +43,7 @@ type Encoder struct {
fileResolver signing.ProtoFileResolver
typeResolver protoregistry.MessageTypeResolver
doNotSortFields bool
indent string
}

// NewEncoder returns a new Encoder capable of serializing protobuf messages to JSON using the Amino JSON encoding
Expand Down Expand Up @@ -67,6 +71,7 @@ func NewEncoder(options EncoderOptions) Encoder {
fileResolver: options.FileResolver,
typeResolver: options.TypeResolver,
doNotSortFields: options.DoNotSortFields,
indent: options.Indent,
}
return enc
}
Expand Down Expand Up @@ -109,10 +114,36 @@ func (enc Encoder) DefineFieldEncoding(name string, encoder FieldEncoder) Encode
return enc
}

// DefineScalarEncoding defines a custom encoding for a protobuf scalar field. The `name` field must match a usage of
// an (cosmos_proto.scalar) option in the protobuf message as in the following example. This encoding will be used
// instead of the default encoding for all usages of the tagged field.
//
// message Balance {
// string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// ...
// }
func (enc Encoder) DefineScalarEncoding(name string, encoder FieldEncoder) Encoder {
if enc.scalarEncoders == nil {
enc.scalarEncoders = map[string]FieldEncoder{}
}
enc.scalarEncoders[name] = encoder
return enc
}

// Marshal serializes a protobuf message to JSON.
func (enc Encoder) Marshal(message proto.Message) ([]byte, error) {
buf := &bytes.Buffer{}
err := enc.beginMarshal(message.ProtoReflect(), buf)

if enc.indent != "" {
indentBuf := &bytes.Buffer{}
if err := json.Indent(indentBuf, buf.Bytes(), "", enc.indent); err != nil {
return nil, err
}

return indentBuf.Bytes(), err
}

return buf.Bytes(), err
}

Expand Down
60 changes: 59 additions & 1 deletion x/tx/signing/aminojson/json_marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,64 @@ func TestDynamicPb(t *testing.T) {
require.NoError(t, err)
dynamicBz, err := encoder.Marshal(dynamicMsg)
require.NoError(t, err)
fmt.Printf("dynamicBz: %s\n", string(dynamicBz))
require.Equal(t, string(bz), string(dynamicBz))
}

func TestIndent(t *testing.T) {
encoder := aminojson.NewEncoder(aminojson.EncoderOptions{Indent: " "})

msg := &testpb.ABitOfEverything{
Message: &testpb.NestedMessage{
Foo: "test",
Bar: 0, // this is the default value and should be omitted from output
},
Enum: testpb.AnEnum_ONE,
Repeated: []int32{3, -7, 2, 6, 4},
Str: `abcxyz"foo"def`,
Bool: true,
Bytes: []byte{0, 1, 2, 3},
I32: -15,
F32: 1001,
U32: 1200,
Si32: -376,
Sf32: -1000,
I64: 14578294827584932,
F64: 9572348124213523654,
U64: 4759492485,
Si64: -59268425823934,
Sf64: -659101379604211154,
}

bz, err := encoder.Marshal(msg)
require.NoError(t, err)
fmt.Println(string(bz))
require.Equal(t, `{
"type": "ABitOfEverything",
"value": {
"bool": true,
"bytes": "AAECAw==",
"enum": 1,
"f32": 1001,
"f64": "9572348124213523654",
"i32": -15,
"i64": "14578294827584932",
"message": {
"foo": "test"
},
"repeated": [
3,
-7,
2,
6,
4
],
"sf32": -1000,
"sf64": "-659101379604211154",
"si32": -376,
"si64": "-59268425823934",
"str": "abcxyz\"foo\"def",
"u32": 1200,
"u64": "4759492485"
}
}`, string(bz))
}

0 comments on commit 91fad07

Please sign in to comment.