JSON和处理未报告的领域
编码/ json不包含未导出的字段是否有技术上的原因? 如果不是这样,这是一个武断的决定,是否可以有一个额外的后门选项(比如说“+”),即使未被引用也是如此?
要求输出客户端代码来获得这个function感觉不幸,特别是如果小写字母提供封装,或者对编组结构的决定比它们的devise晚得多。
人们如何处理这个问题? 只是出口一切?
另外,不输出字段名称使得难以遵循所build议的习惯用法。 我想如果一个结构X有字段Y,你不能有一个访问器方法Y()。 如果你想提供对Y的接口访问,你必须为getter提供一个新的名字,不pipe你会得到什么非惯用的东西,根据http://golang.org/doc/effective_go.html#Getters
有一个技术原因。 json库没有权力使用reflection来查看字段,除非它们被导出。 一个包只能查看自己包中的未导出types的字段
为了处理你的问题,你可以做的是做一个未导出的types与导出的字段。 如果传入Json,它将解组成一个未导出的types,但不会显示在API文档中。 然后您可以制作embedded未导出types的导出types。 这个导出的types将需要方法来实现json.Marshaler
和json.Unmarshaler
接口。
注意:所有的代码都是未经testing的,甚至不能编译。
type jsonData struct { Field1 string Field2 string } type JsonData struct { jsonData } // Implement json.Unmarshaller func (d *JsonData) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &d.jsonData) } // Getter func (d *JsonData) Field1() string { return d.jsonData.Field1 }
斯蒂芬的答案是完整的。 另外,如果你真正想要的只是你的json中的小写键,你可以手动指定键名,如下所示:
type Whatever struct { SomeField int `json:"some_field"` }
以这种方式,编组任何产生字段SomeField的关键字“some_field”(而不是在你的json中有“SomeField”)。
如果您在保留未导出的字段时已经死了,您还可以通过定义一个带有签名MarshalJSON() ([]byte, error)
的方法来实现json.Marshaler接口。 一种方法是使用一个结构字面值,它只是导出了未导出字段的版本,如下所示:
type Whatever struct { someField int } func (w Whatever) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ SomeField int `json:"some_field"` }{ SomeField: w.someField, }) }
这可能有点麻烦,所以你也可以使用map[string]interface{}
如果你喜欢:
func (w Whatever) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "some_field": w.SomeField, }) }
然而,应该注意的是,封送处理interface{}
有一些注意事项,并且可以像uint64
一样执行浮动操作,从而导致精度损失。 (所有代码未经testing)