【问题标题】:Can I access "extra" fields when unmarshalling json in Go?在 Go 中解组 json 时,我可以访问“额外”字段吗?
【发布时间】:2015-12-19 02:54:35
【问题描述】:

假设我有这种类型:

type Foo struct{
   Bar string `json:"bar"`
}

我想将这个 json 解组到其中:

in := []byte(`{"bar":"aaa", "baz":123}`)

foo := &Foo{}
json.Unmarshal(in,foo)

会成功的。我至少想知道在处理过程中跳过了一些字段。有什么好的方法可以访问这些信息吗?

playground snippet

【问题讨论】:

    标签: json go


    【解决方案1】:

    您可能知道,您可以将任何有效的 json 解组为 map[string]interface{}。解组到 Foo 的实例后,已经没有可用的元数据,您可以在其中检查被排除的字段或类似的东西。但是,您可以解组这两种类型,然后检查映射中与 Foo 上的字段不对应的键。

    in := []byte(`{"bar":"aaa", "baz":123}`)
    
    foo := &Foo{}
    json.Unmarshal(in,foo)
    
    allFields := &map[string]interface{}
    json.Unmarshal(in, allFields)
    for k, _ := range allFields {
        fmt.Println(k)
        // could also use reflect to get field names as string from Foo
        // the get the symmetric difference by nesting another loop here
        // and appending any key that is in allFields but not on Foo to a slice
    }
    

    【讨论】:

    • 非常有趣的解决方案。使用深度嵌套的结构可能会有点困难,但应该使用简单的结构。
    • @captncraig 是的,它不太理想。如果您想变得非常认真,我认为您可以通过展平allFields 映射并使用递归算法将所有字段从具体类型中的嵌套结构中取出来实现通用解决方案。获取字段名称的仅供参考可能会觉得这很有用; stackoverflow.com/questions/24337145/…
    • 我真的很喜欢这个 toml 库如何处理它:godoc.org/github.com/BurntSushi/toml#MetaData.Undecoded 但这种事情需要更改核心 json 包:(
    • @captncraig 我不知道这有多可行,只是根据您链接到的软件包想到的一个想法;为interface{} 实现UnmarshalJSON,将调用链接到它的正常版本,但不是在反映类型并检查传入字符串中的所有字段之前。如果您访问 json 标记,则可以通过执行 tag = " + tag + ": 来保证匹配非常好(ofc 在那里正确引用,不知道如何在评论中做到这一点)。输入字符串不会真正引起冲突,因为它们需要转义,所以我认为 string.Contains 相当可靠。
    猜你喜欢
    • 2023-03-14
    • 2010-11-12
    • 2021-12-05
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多