当前位置: 首页 > 知识库问答 >
问题:

如何不使用Go将空结构封送到JSON中?

权胜泫
2023-03-14

我有一个这样的结构:

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包不封送我的空结构字段?

共有3个答案

彭鸿彩
2023-03-14

Data是一个初始化的结构,因此它不被认为是空的,因为encoding/json只查看立即数,而不查看结构中的字段。

不幸的是,从json返回nil。封送拆收器当前不工作:

func (_ MyStruct) MarshalJSON() ([]byte, error) {
    if empty {
        return nil, nil // unexpected end of JSON input
    }
    // ...
}

您也可以给Result一个封送拆收器,但这不值得付出努力。

正如马特所建议的,唯一的选择是将数据设为指针,并将值设置为nil

鲁龙野
2023-03-14

正如@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来完成代码,所以我更喜欢内联以避免混乱。

尹俊雅
2023-03-14

正如医生所说,“任何零指针。”使结构成为指针。指针具有明显的“空”值: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对象。” 因此,我认为您