Golang中如何解析JSON动态字段

Golang中如何解析JSON动态字段 向各位问好,我在将JSON写入Go结构体时遇到了一个之前没碰到过的情况。如果JSON字段是动态变化的,请问该如何在结构体中定义它?例如,JSON包含一个对象数组,但对象的名称可以是任意的,因此我无法像 json:"dynfield" 这样指定它,因为它总是会不同。

JSON

"title1": [
{
      "dynfield1" : {
        "field1" : "value1",
        "field2" : "value2",
         ...
         },
      "dynfield2" : {
        "field1" : "value1",
        "field2" : "value2",
         ...
         },
    }
]

“dynfield”可以是任意值。

type gomarsh struct {
 title1 []title1 `json:"title1"`
 }

 type title1 struct {
 dynfield dynfield `json:"dynfieldn"` // 这里该如何表示
}

更多关于Golang中如何解析JSON动态字段的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

是的,谢谢,我怎么会忘了 Go 语言里的 map。

更多关于Golang中如何解析JSON动态字段的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果我的理解正确,您想要的是:

type gomarhs struct {
  Title1 []map[string]title1 `json:"title1"`
}

type title1 struct {
  Field1 string `json:"field1"`
}

在Go中处理动态字段的JSON时,可以使用map[string]interface{}或自定义json.RawMessage来解析未知字段。以下是两种解决方案:

方案1:使用map[string]interface{}

package main

import (
    "encoding/json"
    "fmt"
)

type Response struct {
    Title1 []map[string]map[string]string `json:"title1"`
}

func main() {
    jsonStr := `{
        "title1": [
            {
                "dynfield1": {
                    "field1": "value1",
                    "field2": "value2"
                },
                "dynfield2": {
                    "field1": "value3",
                    "field2": "value4"
                }
            }
        ]
    }`

    var resp Response
    if err := json.Unmarshal([]byte(jsonStr), &resp); err != nil {
        panic(err)
    }

    // 访问动态字段
    for _, item := range resp.Title1 {
        for dynFieldName, dynFieldValue := range item {
            fmt.Printf("字段名: %s\n", dynFieldName)
            fmt.Printf("field1: %s\n", dynFieldValue["field1"])
            fmt.Printf("field2: %s\n", dynFieldValue["field2"])
        }
    }
}

方案2:使用json.RawMessage进行延迟解析

package main

import (
    "encoding/json"
    "fmt"
)

type Response struct {
    Title1 []map[string]json.RawMessage `json:"title1"`
}

type DynField struct {
    Field1 string `json:"field1"`
    Field2 string `json:"field2"`
}

func main() {
    jsonStr := `{
        "title1": [
            {
                "dynamic_field_1": {
                    "field1": "value1",
                    "field2": "value2"
                },
                "another_field": {
                    "field1": "value3",
                    "field2": "value4"
                }
            }
        ]
    }`

    var resp Response
    if err := json.Unmarshal([]byte(jsonStr), &resp); err != nil {
        panic(err)
    }

    // 动态解析每个字段
    for _, item := range resp.Title1 {
        for fieldName, rawData := range item {
            var dynField DynField
            if err := json.Unmarshal(rawData, &dynField); err != nil {
                fmt.Printf("解析字段 %s 失败: %v\n", fieldName, err)
                continue
            }
            fmt.Printf("字段名: %s, field1: %s, field2: %s\n", 
                fieldName, dynField.Field1, dynField.Field2)
        }
    }
}

方案3:使用灵活的结构体组合

package main

import (
    "encoding/json"
    "fmt"
)

type Response struct {
    Title1 []DynamicObject `json:"title1"`
}

type DynamicObject map[string]DynField

type DynField struct {
    Field1 string `json:"field1"`
    Field2 string `json:"field2"`
}

func main() {
    jsonStr := `{
        "title1": [
            {
                "user_123": {
                    "field1": "value1",
                    "field2": "value2"
                },
                "item_456": {
                    "field1": "value3",
                    "field2": "value4"
                }
            }
        ]
    }`

    var resp Response
    if err := json.Unmarshal([]byte(jsonStr), &resp); err != nil {
        panic(err)
    }

    // 类型安全地访问数据
    for _, obj := range resp.Title1 {
        for key, value := range obj {
            fmt.Printf("Key: %s, Field1: %s, Field2: %s\n", 
                key, value.Field1, value.Field2)
        }
    }
}

方案4:完全动态解析(适用于字段结构也未知的情况)

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonStr := `{
        "title1": [
            {
                "dynamic_key_1": {
                    "field1": "value1",
                    "field2": "value2",
                    "extra_field": "extra_value"
                },
                "dynamic_key_2": {
                    "field1": "value3",
                    "field2": "value4"
                }
            }
        ]
    }`

    var data map[string]interface{}
    if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
        panic(err)
    }

    // 遍历所有动态字段
    title1 := data["title1"].([]interface{})
    for _, item := range title1 {
        itemMap := item.(map[string]interface{})
        for dynKey, dynValue := range itemMap {
            fmt.Printf("动态字段名: %s\n", dynKey)
            
            // dynValue 是 interface{},可以进一步断言
            if subMap, ok := dynValue.(map[string]interface{}); ok {
                for k, v := range subMap {
                    fmt.Printf("  %s: %v\n", k, v)
                }
            }
        }
    }
}

这些方案中,方案3提供了最好的类型安全性和代码清晰度,方案2提供了最大的灵活性,方案1最简单直接,方案4适用于完全未知的JSON结构。根据你的具体需求选择合适的方法。

回到顶部