我有一个这样的结构:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
但是,即使MyStruct的实例完全为空(也就是说,所有值都是默认值),它也被序列化为:
"data":{}
我知道编码/json文档指定“空”字段是:
false、0、任何nil指针或接口值,以及任何长度为零的数组、切片、映射或字符串
但不考虑所有空/默认值的结构。它的所有字段也用omitair
标记,但这没有效果。
如何让JSON包不封送我的空结构字段?
Data
是一个初始化的结构,因此它不被认为是空的,因为encoding/json
只查看立即数,而不查看结构中的字段。
不幸的是,从json返回
nil
。封送拆收器当前不工作:
func (_ MyStruct) MarshalJSON() ([]byte, error) {
if empty {
return nil, nil // unexpected end of JSON input
}
// ...
}
您也可以给
Result
一个封送拆收器,但这不值得付出努力。
正如马特所建议的,唯一的选择是将
数据
设为指针,并将值设置为nil
。
正如@chakrit在一篇评论中提到的,您无法通过实现json来实现这一点。MyStruct上的封送拆收器
,并在使用它的每个结构上实现自定义JSON封送函数可能需要做很多工作。这实际上取决于您的用例是否值得付出额外的工作,或者您是否准备在JSON中使用空结构,但下面是我用于结果的模式:
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来完成代码,所以我更喜欢内联以避免混乱。
正如医生所说,“任何零指针。”使结构成为指针。指针具有明显的“空”值:nil
。
修复-定义具有结构指针字段的类型:
type Result struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
然后是这样的值:
result := Result{}
将列表为:
{}
说明:注意类型定义中的*MyStruct
。JSON序列化并不关心它是否是指针——这是一个运行时细节。因此,将结构字段变成指针只会影响编译和运行时)。
请注意,如果将字段类型从MyStruct
更改为*MyStruct
,则需要指向结构值的指针来填充它,如下所示:
Data: &MyStruct{ /* values */ }
问题内容: 我有一个这样的结构: 但是,即使MyStruct实例完全为空(意味着所有值都是默认值),它也会被序列化为: 我知道encoding / json文档指定“空”字段为: false,0,任何nil指针或接口值以及任何长度为零的数组,切片,映射或字符串 但不考虑具有所有空/默认值的结构。它的所有字段也都标有,但这无效。 如何获取JSON包以 不 封送我的字段为空结构? 问题答案: 正如文档
问题内容: 我正在尝试通过创建JSON文件并将其解析为结构来配置Go程序: config.json文件: 该程序可以编译并运行,没有任何错误,但是print语句输出: (错误和两个空字符串) 我也尝试过,但结果相同。 如何以填充结构值的方式解析JSON? 问题答案: 您没有导出struct元素。它们都以小写字母开头。 将结构元素的首字母大写以将其导出。JSON编码器/解码器不会使用未导出的结构元素
我确实有这个要求 如果我没有在json请求正文中发送,则解组会在不返回错误的情况下分配“”,我想知道是否有类似的情况 因此,如果字段不存在或为空,则解组返回错误。 提前谢谢
问题内容: 我有一个结构,其中包含要编码为JSON的字符串作为[] byte字段。但是,生成的JSON包含切片内容的非预期字符串表示形式。这是我所引用的示例: 这将产生以下输出: json.Marshal()方法对[] byte编码的字符串执行哪种转换。如何生成带有字符串{“ Content”:“ Hello”}的原始内容的JSON? 问题答案: 将A 编组为base64编码的字符串。从文档中:
问题内容: 在将结果转换为JSON之前,我不想使用结构。假设我有一些结果: 我可以在 docs 变量中收集所有结果,并在 doc 变量中收集最后一个结果: 我可以轻松地将最后的结果转换为JSON,而无需使用任何结构: 我无法将文档转换为JSON,因此无法在我的Rest服务器中使用。 更新2019-01-17: 我在我的REST服务器中使用result像这样: 因此它不可能是遍历值的循环。问题:如何
问题内容: 我的成员有一个结构,我正在用编写它。麻烦的是,它将s解释为s,并且它输出字符串而不是数字数组。 如果它是,我可以使它工作,但是如果可以避免的话,我不想分配和复制这些项目。我可以吗? 问题答案: 根据文档,a 将被编码为Base64字符串。 “数组和切片值编码为JSON数组, 除了[] byte编码为base64编码的字符串 ,而nil slice编码为空JSON对象。” 因此,我认为您