JSON和处理未导出的字段

use*_*952 62 json go

编译/ json中是否存在未包含未导出字段的技术原因?如果没有,这是一个任意的决定可以有一个额外的后门选项(说'+')包括即使未导出?

要求客户端代码导出以获得此功能感觉很不幸,特别是如果小写提供封装或者对编组结构的决定要比它们的设计晚得多.

人们如何处理这个问题?只出口一切?

此外,不导出字段名称使得难以遵循建议的习语.我认为如果结构X有字段Y,则不能有一个存取方法Y().如果你想提供对Y的界面访问,你必须为getter提出一个新的名字,不管你会得到什么非惯用的东西,根据http://golang.org/doc/effective_go.html#Getters

Ste*_*erg 94

有一个技术原因.除非导出,否则json库无法使用reflect查看字段.包只能在其自己的包中查看未导出的类型字段

为了解决您的问题,您可以做的是使用导出的字段创建一个未导出的类型.如果传递给它没有问题,Json将解组为未导出的类型,但它不会出现在API文档中.然后,您可以创建嵌入未导出类型的导出类型.然后,此导出类型将需要方法来实现json.Marshalerjson.Unmarshaler接口.

注意:所有代码都是未经测试的,甚至可能无法编译.

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
}
Run Code Online (Sandbox Code Playgroud)

  • 我在节目中有点迟了,但......在上面的工作中,Field1和Field2 _are_导出.您可以在该包之外读取和写入JsonData的Field1和Field2(带有大写字母J).因此,虽然这在理论上很酷,但它实际上与输出类型和字段没有任何不同. (5认同)

jor*_*lli 59

斯蒂芬的回答是完整的.顺便说一句,如果你真正想要的是json中的小写键,你可以手动指定键名,如下所示:

type Whatever struct {
    SomeField int `json:"some_field"`
}
Run Code Online (Sandbox Code Playgroud)

以这种方式,编组Whatever为字段SomeField产生关键字"some_field"(而不是在你的json中有"SomeField").

如果您保留未保存的字段,则还可以通过定义带签名的方法来实现json.Marshaler接口MarshalJSON() ([]byte, error).一种方法是使用一个只有导出版本的未导出字段的结构文字,如下所示:

type Whatever struct {
    someField int
}

func (w Whatever) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct{
        SomeField int `json:"some_field"`
    }{
        SomeField: w.someField,
    })
}
Run Code Online (Sandbox Code Playgroud)

这可能有点麻烦,所以map[string]interface{}如果您愿意,也可以使用a :

func (w Whatever) MarshalJSON() ([]byte, error) {
    return json.Marshal(map[string]interface{}{
        "some_field": w.SomeField,
    })
}
Run Code Online (Sandbox Code Playgroud)

然而,应该注意的是,编组interface{}有一些注意事项,并且可以执行诸如编组uint64浮动之类的操作,从而导致精度损失.(所有代码未经测试)

  • JSON不是JavaScript.JSON规范仅说明哪些字符是可接受的,而不是哪些数字范围有效.像876234958273645982736459827346598237465923847561203947812435968234659827346这样的数字在JSON中仍然有效,即使它无法被JavaScript理解.对于一个真实世界的例子,Twitter API将推文ID表示为64位无符号整数,这在JavaScript中无效,但是是有效的JSON. (18认同)
  • 目前,所有这些都是正确的,但名称仍然是 JSON,历史上代表“JavaScript 对象表示法”。其中一个令人惊讶的微小位让您想将其重命名为 NJSON(NewJSON 或更确切地说 NotJavaScript):) (2认同)