Struct含有匿名字段,该匿名字段有MarshalJSON方法,导致Struct不能正确转换成json字符串!!

harrykobe · · 1868 次点击
我们在业务中,有大量的自定义基本类型作为枚举约束使用,都可以读写库的。
#4
更多评论
我的理解,问题是两个。 1、如何正确输出: ```Go {"Name":"BOB","jobRole":"Sales"} ``` 在overflow说明很清楚,如果要自己实现MarshalJSON,那么就要重新定义被struct使用的属性类型。原文如下: >To solve this more generically you're going to have to implement MarshalJSON on the outer type. Methods on the inner type are promoted to the outer type so you're not going to get around that. You could have the outer type call the inner type's MarshalJSON then unmarshal that into a generic structure like map[string]interface{} and add your own fields. This example does that but it has a side effect of changing the order of the final output fields 如果不这么做,那么对于绑定的符合属性,则会因为属性具有MarshalJSON方法,而中断Marshal。 因此,要实现楼主要求的代码为: ```Go package main import ( "encoding/json" "fmt" "strings" ) type NAME string func (n NAME )MarshalJSON()([]byte,error){ return json.Marshal(strings.ToUpper(string(n))) } type Person struct { Name NAME `json:"Name"` } type Employee struct { Person JobRole string `json:"jobRole"` } func main() { foo1() } func foo1() { p := Person{"Bob"} e := Employee{p, "Sales"} output, _ := json.Marshal(e) fmt.Printf("%s\n", string(output)) } ``` >PS:按照示例代码,无法重现,怀疑是接收器多了个指针"*"。 2、死循环 很明显,不存在,否则不会输出答案。 具体实现逻辑是:Marshal-->e.reflectValue-->valueEncoder-->typeEncoder-->newTypeEncoder。 ```Go // newTypeEncoder constructs an encoderFunc for a type. // The returned encoder only checks CanAddr when allowAddr is true. func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { if t.Implements(marshalerType) { return marshalerEncoder } if t.Kind() != reflect.Ptr && allowAddr { if reflect.PtrTo(t).Implements(marshalerType) { return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false)) } } //.... } ``` 从newTypeEncoder函数中可以看出,如果示例中的Employee具有MarshalJSON方法,则直接调用并返回,并不会再次调用其属性Person的MarshalJSON了,更不会有死循环的情况发生。
#1
其实overflow里面说的这个方法不是不可以,只是这个结构体可能有很多用途,比如ORM需要判断里面的类型从而对它进行转换,现在将NAME的string类型换成了NAME类型,这样就会导致ORM检测不了类型,写不进数据库
#2