Go语言 JSON和处理未导出的字段

zpjtge22  于 2023-03-16  发布在  Go
关注(0)|答案(2)|浏览(227)

编码/json不包含未导出的字段是否有技术原因?如果没有,并且是任意决定,是否有额外的后门选项(如'+')可以包含,即使未导出?
要求导出客户机代码以获得此功能感觉很不合适,尤其是在小写提供封装或封送结构的决定比设计它们晚得多的情况下。
人们是怎么处理的?把所有东西都出口?
另外,导出字段名是否会使遵循建议的习惯用法变得困难?我认为如果结构体X有字段Y,则不能有访问方法Y()。如果要提供对Y的接口访问,则必须为getter提供新名称,无论如何,根据www.example.com,您将得到一些不习惯用法的内容http://golang.org/doc/effective_go.html#Getters

to94eoyn

to94eoyn1#

这是一个技术上的原因,json库不能使用reflect查看字段,除非它们被导出,一个包只能查看它自己包中类型的未导出字段
为了解决你的问题,你可以做的是创建一个带有导出字段的未导出类型。如果没有问题地传递给json,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
}
bvn4nwqk

bvn4nwqk2#

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

type Whatever struct {
    SomeField int `json:"some_field"`
}

通过这种方式,封送一个Whatever会为字段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封送为浮点数,从而导致精度损失。(所有代码都未经测试)

相关问题