如何正确解组一个不同类型的数组? [英] How to unmarshall an array of different types correctly?

查看:108
本文介绍了如何正确解组一个不同类型的数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只要我有键值对,unmarshalling是非常直接的,但我将如何以不同顺序解组一个不同类型的数组?单个元素已被很好地定义并且已知,但命令不是。

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



我会尝试所有元素的错误吗?
是否有某种类型的工会可以为我做这件事?



游乐场版本

 包主

导入(
encoding / json
fmt


var my_json string =`{
an_array:[
with_a字符串,
{
和:some_more,
different:[嵌套,类型]
}
]


类型MyInner结构{
和字符串
不同[]字符串
}

类型MyJSON结构{
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.Print ln(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)
}
}


解决方案

Go官方博客有一篇不错的文章关于 encoding / json JSON和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:=范围vf {
switch vv:= v。(type){
case string:
fmt.Printf(%v:is string - %q \\\
,k,vv)
case int:
fmt.Printf(%v:is int - %q\\\
,k,vv)
默认值:
fmt。 Printf(%v:,k)
WTHisThisJSON(v)
}

}
case [] interface {}:
fmt.Println(是一个数组:)
for k ,v:= range vf {
switch vv:= v。(type){
case string:
fmt.Printf(%v:is string - %q \\\
, k,vv)
case int:
fmt.Printf(%v:is int - %q\\\
,k,vv)
默认值:
fmt.Printf (%v:,k)
WTHisThisJSON(v)
}

}
}
}

func main(){

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


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,
{
和:some_more,
different:[nested,types]]



$ b JSON:是一个映射:
an_array:是一个数组:
0:是字符串 - with_a字符串
1:是地图:
和:是字符串 - some_more
不同:是一个数组:
0:是字符串 - 嵌套
1:是字符串 - 类型

目前还不完整,但显示了它将如何工作。 / p>

As long as I have key-value pairs unmarshalling is pretty straight forward but how would I unmarshall an array of different types in different order? The single elements are well defined and known but the order is not.

I can not come up with a beautiful solution.

Would I try and error over all elements? Is there some kind of union type that could do that for me?

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)
        }
    }
}

解决方案

Go official blog has a nice article about encoding/json: JSON and GO. It's possible to "Decode arbitrary data" into an interface{} and use type assertion to determine the type dynamically.

Your code can be probably modified to this:

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)
    }
}

It gives output as follows:

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"

It's not complete yet, but shows how it's gonna work.

这篇关于如何正确解组一个不同类型的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆