go-yaml / yaml

YAML support for the Go language.
Other
6.83k stars 1.04k forks source link

gRPC: omitempty and `-` #367

Open albttx opened 6 years ago

albttx commented 6 years ago

from encoding/json package:

 The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.

As a special case, if the field tag is "-", the field is always omitted. Note that a field with name "-" can still be generated using the tag "-,". 

I currently working with data structure generated with protocol-buffer and the struct have:

type MyStruct struct {
    VarName          []*Vars `protobuf:"bytes,1,rep,name=varname" json:"vars,omitempty"`
    XXX_NoUnkeyedLiteral struct{}      `json:"-"`
    XXX_unrecognized     []byte        `json:"-"`
    XXX_sizecache        int32         `json:"-"`
}

I know grpc handle write json:"-" and not yaml:"-", but i might be nice to consider handle it

NathanBaulch commented 4 years ago

Not ideal, but you can work around this issue by pre-processing your struct using mapstructure with its nifty DecoderConfig.TagName config option set to "json".

m := make(map[string]interface{})
config := &mapstructure.DecoderConfig{Result: &m, TagName: "json"}
if decoder, err := mapstructure.NewDecoder(config); err != nil {
    return err
} else if err := decoder.Decode(v); err != nil {
    return err
}
return yaml.Marshal(m)

I know you're not a fan @niemeyer but we really need some way to handle generated/external models (especially gRPC).

EDIT: mapstructure only processes the root object. For a full recursive solution you can use structs instead since it also supports a configurable tag name (ahem, very handy convention!).

s := structs.New(v)
s.TagName = "json"
return yaml.Marshal(s.Map())