如何正确解组不同类型的数组?

Posted

技术标签:

【中文标题】如何正确解组不同类型的数组?【英文标题】:How to unmarshall an array of different types correctly? 【发布时间】:2012-11-02 02:02:11 【问题描述】:

只要我有键值对,解组非常简单,但我如何以不同的顺序解组不同类型的数组?单个元素定义明确且已知,但顺序不明确。

我想不出一个漂亮的解决方案。

我会尝试在所有元素上出错吗? 是否有某种联合类型可以为我做到这一点?

playground version

package main

import (
    "encoding/json"
    "fmt"
)

var my_json string = `
    "an_array":[
        "with_a string",
        
            "and":"some_more",
            "different":["nested", "types"]
        
    ]
`

type MyInner struct 
    And     string
    Different   []string


type MyJSON struct 
    An_array []json.RawMessage


func main() 
    var my_json_test MyJSON

    e := json.Unmarshal([]byte(my_json), &my_json_test)
    if e != nil 
        fmt.Println(e)
     else 
        for index, value := range my_json_test.An_array 
            fmt.Println("index: ", index)
            fmt.Println("value: ", string(value))
        
        var my_inner MyInner
        err := json.Unmarshal(my_json_test.An_array[1], &my_inner)
        if err != nil 
            fmt.Println(err)
         else 
            fmt.Println("inner structure: ", my_inner)
        
    

【问题讨论】:

【参考方案1】:

Go 官方博客有一篇关于encoding/json 的好文章:JSON and GO。可以将任意数据“解码”到接口中,并使用类型断言来动态确定类型。

你的代码大概可以修改成这样:

package main

import (
    "encoding/json"
    "fmt"
)

var my_json string = `
    "an_array":[
    "with_a string",
    
        "and":"some_more",
        "different":["nested", "types"]
    
    ]
`

func WTHisThisJSON(f interface) 
    switch vf := f.(type) 
    case map[string]interface:
        fmt.Println("is a map:")
        for k, v := range vf 
            switch vv := v.(type) 
            case string:
                fmt.Printf("%v: is string - %q\n", k, vv)
            case int:
                fmt.Printf("%v: is int - %q\n", k, vv)
            default:
                fmt.Printf("%v: ", k)
                WTHisThisJSON(v)
            

        
    case []interface:
        fmt.Println("is an array:")
        for k, v := range vf 
            switch vv := v.(type) 
            case string:
                fmt.Printf("%v: is string - %q\n", k, vv)
            case int:
                fmt.Printf("%v: is int - %q\n", k, vv)
            default:
                fmt.Printf("%v: ", k)
                WTHisThisJSON(v)
            

        
    


func main() 

    fmt.Println("JSON:\n", my_json, "\n")

    var f interface
    err := json.Unmarshal([]byte(my_json), &f)
    if err != nil 
        fmt.Println(err)
     else 
        fmt.Printf("JSON: ")
        WTHisThisJSON(f)
    

输出如下:

JSON:
 
    "an_array":[
    "with_a string",
    
        "and":"some_more",
        "different":["nested", "types"]
    
    ]
 

JSON: is a map:
an_array: is an array:
0: is string - "with_a string"
1: is a map:
and: is string - "some_more"
different: is an array:
0: is string - "nested"
1: is string - "types"

它还没有完成,但展示了它是如何工作的。

【讨论】:

正是我想要的。 我这边缺少的部分是type assertion

以上是关于如何正确解组不同类型的数组?的主要内容,如果未能解决你的问题,请参考以下文章

json:无法将字符串解组为 MyMap.map 类型的 Go 值

如何编组/解组在 Go 中有两种不同格式的通用 JSON 和 BSON 键/字段?

Swift 中的复杂 JSON。如何正确获取数据。不同的结构

在 Golang 中解组 XML 时如何在 interface 中获取数据?

为不同类型的项目数组正确的 JSON Schema

恐慌:json:无法将数组解组为 main.Structure 类型的 Go 值