Skip to content

jsonpb marshaling Any containing dynamic message missing @type #360

Closed
@cybrcodr

Description

@cybrcodr

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"}}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions