Skip to content

jsonpb marshaling Any containing dynamic message missing @type #360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cybrcodr opened this issue May 26, 2017 · 2 comments
Closed

jsonpb marshaling Any containing dynamic message missing @type #360

cybrcodr opened this issue May 26, 2017 · 2 comments

Comments

@cybrcodr
Copy link
Contributor

Sample proto file

syntax = "proto2";
package pb;

message Foo {
  optional google.protobuf.Any iany = 1;
}

Sample code that stores a dynamic message into Foo.iany field.

package test

import (
        "strings"
        "testing"

        "test/pb"

        "github.com/golang/protobuf/jsonpb"
        "github.com/golang/protobuf/proto"
        anypb "github.com/golang/protobuf/ptypes/any"
)

type dynamic struct {
        Json []byte `protobuf:"bytes,1,opt,name=json" json:"json,omitempty"`
}

func (d *dynamic) Reset() {
        d.Json = nil
}

func (d *dynamic) String() string {
        return string(d.Json)
}

func (d *dynamic) ProtoMessage() {}

func (d *dynamic) MarshalJSONPB(_ *jsonpb.Marshaler) ([]byte, error) {
        return d.Json, nil
}

func (d *dynamic) UnmarshalJSONPB(_ *jsonpb.Unmarshaler, jstr []byte) error {
        d.Json = jstr
        return nil
}

func init() {
        proto.RegisterType((*dynamic)(nil), "pb.Dynamic")
}

func TestMarshalAnyDynamic(t *testing.T) {
        d := &dynamic{Json: []byte(`{"hello": "world"}`)}
        b, err := proto.Marshal(d)
        if err != nil {
                t.Fatal(err)
        }

        foo := &pb.Foo{
                Iany: &anypb.Any{
                        TypeUrl: "ok.com/pb.Dynamic",
                        Value:   b,
                },
        }

        m := &jsonpb.Marshaler{}
        s, err := m.MarshalToString(foo)
        if err != nil {
                t.Error(err)
        } else {
                t.Log(s)
        }
}

Outputs:

{"iany":{"hello": "world"}}

Per JSON mapping spec (https://developers.google.com/protocol-buffers/docs/proto3#json)

If the Any contains a value that has a special JSON mapping, it will be converted as follows: {"@type": xxx, "value": yyy}. Otherwise, the value will be converted into a JSON object, and the "@type" field will be inserted to indicate the actual data type.

Output is missing "@type" key-value. I'm going to treat dynamic message as the latter case, i.e. not having any special JSON mapping. So, above should have output

{"iany":{"@type":"ok.com/pb.Dynamic", "hello": "dynamic"}}
@cybrcodr
Copy link
Contributor Author

Here's a description of a possible solution ...

In the following block for calling JSONPBMarshaler.MarshalJSONPB ...
https://github.com/golang/protobuf/blob/master/jsonpb/jsonpb.go#L121

if typeURL != "", need to add @type key-value into the resulting json bytes.

cybrcodr pushed a commit that referenced this issue May 31, 2017
…rshaler (#361)


* Fix marshaling of Any containing object that implements JSONPBMarshaler.
* Add test for marshaling Any that implements JSONPBMarshaler.
* Add test for unmarshaling Any that implements JSONPBUnmarshaler.

Fixed issue #360.
@cybrcodr
Copy link
Contributor Author

Fixed in 6e4cc92

@golang golang locked and limited conversation to collaborators Jun 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant