我有这样的结构:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
但即使MyStruct的实例完全为空(意味着所有值都是默认值),它也会被序列化为:
"data":{}
我知道encoding/json文档指定“空”字段为:
false,0,任何nil指针或接口值,以及任何数组, 切片,地图或长度为零的字符串
但没有考虑具有所有空/默认值的结构。它的所有字段也都标有omitempty
,但这没有效果。
如何让不的JSON包封送我的空结构字段?
答案 0 :(得分:97)
哦!轻松修复:“任何无指针。” - 使结构成为指针。
修正:
type Result struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
注意*MyStruct
- 当我现在创建MyStruct
时,我只是参考:
myStruct := &MyStruct{ /* values */ }
现在,“空”MyStruct
不再按照需要编组到JSON中。
答案 1 :(得分:7)
正如@chakrit在评论中提到的那样,你无法通过在json.Marshaler
上实现MyStruct
来实现这一点,并且在每个使用它的结构上实现自定义JSON编组功能可能会很多更多的工作。这取决于你的用例是否值得额外的工作,或者你是否准备好在你的JSON中使用空结构,但这是我用于Result
的模式:
type Result struct {
Data MyStruct
Status string
Reason string
}
func (r Result) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}{
Data: &r.Data,
Status: r.Status,
Reason: r.Reason,
})
}
func (r *Result) UnmarshalJSON(b []byte) error {
decoded := new(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
})
err := json.Unmarshal(b, decoded)
if err == nil {
r.Data = decoded.Data
r.Status = decoded.Status
r.Reason = decoded.Reason
}
return err
}
如果你有很多字段的巨大结构,这可能会变得乏味,特别是稍后更改结构的实现,但是不能重写整个json
包以满足你的需要(不是一个好主意),这几乎是我仍然可以想到完成这项任务的唯一方法,同时仍然保持非指针MyStruct
。
此外,您不必使用内联结构,您可以创建命名结构。我使用LiteIDE代码完成,所以我更喜欢内联以避免混乱。
答案 2 :(得分:6)
Data
是一个初始化的结构,所以它不被认为是空的,因为encoding/json
只查看立即值,而不是结构内的字段。
很遗憾,从nil
返回json.Marhsler
目前无效:
func (_ MyStruct) MarshalJSON() ([]byte, error) {
if empty {
return nil, nil // unexpected end of JSON input
}
// ...
}
你也可以给Result
一个封送者,但这不值得。
Matt建议,唯一的选择是使Data
指针并将值设置为nil
。
答案 3 :(得分:0)
此功能具有出色的Golang proposal,该功能已经使用了4年以上,因此,可以安全地假设它不会很快进入标准库。正如@Matt指出的那样,传统方法是将结构转换为 pointers-to-structs 。如果这种方法不可行(或不切实际),那么另一种方法是使用备用json编码器,该编码器支持省略零值结构。
我创建了Golang json库( clarketm/json )的镜像,并在<{>}标签为omitempty
时添加了对省略零值结构的支持。应用。该库以类似于go-yaml的流行YAML编码器recursively checking the public struct fields的方式检测零度。
例如
$ go get -u "github.com/clarketm/json"
import (
"fmt"
"github.com/clarketm/json" // drop-in replacement for `encoding/json`
)
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
j, _ := json.Marshal(&Result{
Status: "204",
Reason: "No Content",
})
fmt.Println(string(j))
// Note: `data` is omitted from the resultant json.
{
"status": "204"
"reason": "No Content"
}