【发布时间】:2022-02-11 05:00:54
【问题描述】:
鉴于以下 JSON
{
"some": "value"
"nested": {
"some": "diffvalue",
"nested": {
"some": "innervalue"
}
}
}
大致翻译为这个结构:
type Envelope struct {
some string `json:"some"`
nested InnerEnvelope `json:"nested"`
}
InnerEnvelope 是:type InnerEnvelope map[string]interface{}
由于原始 JSON 的递归类型性质,在这里运行一个简单的 json.Unmarshal([]byte value, &target) 没有帮助。
我不知道内部映射将存在多深以及在哪些键下存在,因此我无法预先声明类型。
这个想法是,使用map[string]interface{} 作为类型还不够好,因为我需要以某种方式转换和键入InnerEnvelope 中的值。细节并不重要,但图像,我需要将 bool 类型的 NestedEnvelope 中的每个值转换为字符串,表示“true”或“false”,而不是实际的 bool 类型。
我转向UnmarshalJSON接口解决了这个问题。我可以像这样在顶层轻松做到这一点:
func (m *Envelope) UnmarshalJSON(b []byte) error {
var stuff noBoolMap
if err := json.Unmarshal(b, &stuff); err != nil {
return err
}
for key, value := range stuff {
switch value.(type) {
case bool:
stuff[key] = strconv.FormatBool(value.(bool))
}
}
return nil
}
但由于内部 json.Unmarshal 已经将内部映射解析为 map[string]interface{},我需要再次遍历内部映射,将它们转换为适当的类型并执行我的值转换。
所以我的问题是:在这种情况下,Go 中的处理方式是什么,最好一次性完成?
上述 JSON 示例的预期结果是:
Envelope {
some: string
nested: InnerEnvelope {
some: string {
nested: InnerEnvelope {
some: string
}
}
}
【问题讨论】:
-
简短的回答是肯定的,您需要将
interface{}转换为string或可能另一个map[string]interface{},因为正如您所提到的,您在编译时不知道结构。 -
“我不知道前面..内部映射将存在于哪些键下,所以我不能预先声明类型。..使用 map[string]interface{} 因为类型不好够了,因为我需要以某种方式转换和输入 InnerEnvelope 中的值。”听起来你有矛盾
-
我不明白你为什么觉得你需要一个自定义的解组方法。 Go 支持递归数据类型就好了:play.golang.org/p/v4hKMTpGSWu.
-
@Peter 澄清一下,示例应该说明
nested1、nested2等等,我不会事先知道嵌套结构将在哪些键下。 @Vorsprung:你在哪里看到了矛盾?