JSON在go中将同一结构编组/解编组为不同的JSON格式?
我有一个结构,我想根据上下文的不同将其封送到JSON中 例如,有时我想这样封送:JSON在go中将同一结构编组/解编组为不同的JSON格式?,json,struct,go,marshalling,unmarshalling,Json,Struct,Go,Marshalling,Unmarshalling,我有一个结构,我想根据上下文的不同将其封送到JSON中 例如,有时我想这样封送: type MyStruct struct { Nickname string `json:"nickname"` EmailAddress string `json:"email_address"` PhoneNumber string `json:"-"` MailingAddress string `json:"-"`
type MyStruct struct {
Nickname string `json:"nickname"`
EmailAddress string `json:"email_address"`
PhoneNumber string `json:"-"`
MailingAddress string `json:"-"`
}
type MyStruct struct {
Nickname string `json:"nickname"`
EmailAddress string `json:"email_address"`
PhoneNumber string `json:"phone_number"`
MailingAddress string `json:"mailing_address"`
}
有时我想这样做:
type MyStruct struct {
Nickname string `json:"nickname"`
EmailAddress string `json:"email_address"`
PhoneNumber string `json:"-"`
MailingAddress string `json:"-"`
}
type MyStruct struct {
Nickname string `json:"nickname"`
EmailAddress string `json:"email_address"`
PhoneNumber string `json:"phone_number"`
MailingAddress string `json:"mailing_address"`
}
有没有一种简单的方法可以做到这一点,而无需:
您可以使用反射,这并不是最有效的解决方案,但它很方便
func MarshalSubset(obj interface{}, fields ...string) ([]byte, error) {
if len(fields) == 0 {
return json.Marshal(obj)
}
out := make(map[string]interface{}, len(fields))
val := reflect.ValueOf(obj)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
if val.Kind() != reflect.Struct {
panic("not a struct")
}
typ := val.Type()
for _, f := range fields {
val := val.FieldByName(f).Interface()
rfld, _ := typ.FieldByName(f)
tag := strings.Split(rfld.Tag.Get("json"), ",")
if len(tag) > 0 {
f = tag[0]
}
out[f] = val
}
return json.Marshal(out)
}
我知道您明确提到“不编写自定义封送拆收器”,但如果有人看到这一点并认为由于复杂性应该避免,则自定义封送拆收器执行您想要执行的操作非常简单:
type MyStruct struct {
Nickname string `json:"nickname"`
EmailAddress string `json:"email_address"`
PhoneNumber string `json:"phone_number"`
MailingAddress string `json:"mailing_address"`
all bool
}
func (ms MyStruct) MarshalJSON() ([]byte, error) {
m := map[string]interface{}{} // ideally use make with the right capacity
m["nickname"] = ms.Nickname
m["email_address"] = ms.EmailAddress
if ms.all {
m["phone_number"] = ms.PhoneNumber
m["mailing_address"] = ms.MailingAddress
}
return json.Marshal(m)
}
如果all
字段应由外部包设置,则可以在结构上定义一个方法,或者将该字段公开(不会影响JSON,因为它是通过自定义封送拆收器编码的)
操场上的可运行示例:这比我想象的要简单得多。最后,我结合使用了这种方法和这里描述的方法:这里有一些链接供参考:封送拆收器类型。博客文章:同样的原则也适用于解封-