将带有任意键/值对的JSON反序列化为结构体。

6

问题

发现很多类似的问题(标题),但没有一个解决了我的问题,所以在这里呈现。

我有一个JSON字符串,其中包含一些已知字段(应始终存在)以及任意数量的未知/任意字段。

示例

{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}

在这个例子中,known1known2 是已知的字段。而 unknown1unknown2 则是任意/未知的字段。

未知的字段可以有任何名称 (键) 和任何值。值的类型可以是字符串、布尔、浮点数或整数。

我的目标是找到解析这种消息最简单和最优雅(惯用)的方法。

我的解决方案

我使用了以下结构体:

type Message struct {
    Known1   string `json:"known1"`
    Known2   string `json:"known2"`
    Unknowns []map[string]interface{}
}

预期结果

使用这个结构体和上面的示例JSON消息,我想要实现一个类似以下输出的Message(来自于fmt.Printf("%+v", msg)):

{Known1:foo Known2:bar Unknowns:[map[unknown1:car] map[unknown2:1]]}

尝试

1. 简单的解组

https://play.golang.org/p/WO6XlpK_vJg

这个方法行不通,Unknowns 没有像预期的那样填充剩余的未知键/值对。

2. 双重解组

https://play.golang.org/p/Mw6fOYr-Km8

这个方法行得通,但我需要两个解组过程,一个用于填充已知字段(使用别名类型以避免无限循环),第二个用于获取所有字段作为 map[string]interface{} 并处理未知字段。

3. 解组和类型转换

https://play.golang.org/p/a7itXObavrX

这个方法行得通,似乎是我的解决方案中最好的选择。

还有其他选项吗?

选项2和3可以行得通,但我很好奇是否有更简单/更优雅的解决方案。

2个回答

2

TMTOWTDI,我认为您找到了一个合理的解决方案。您可以考虑另一种选项 - 与您的第二个选项类似 - 将其反序列化到 map[string]interface{} 上。

然后遍历键和值,并根据需要对值进行类型断言来处理数据。根据您需要做什么,您可能会跳过结构体,或者仍然填充它。

最初的回答

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonMsg := `{"known1": "foo", "known2": "bar", "unknown1": "car", "unknown2": 1}`
    var msg map[string]interface{}
    fmt.Println(json.Unmarshal([]byte(jsonMsg), &msg))
    fmt.Printf("%+v", msg)
}

prints

<nil>
map[known1:foo known2:bar unknown1:car unknown2:1]

https://play.golang.org/p/Bl99Cq5tFWW


嗨,谢谢你的回答。那基本上就是我的第三个解决方案。 - J. Carl

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接