解码map和数组json

时间:2016-08-23 09:18:26

标签: arrays json parsing dictionary go

如果没有项目,外部API将返回空数组:

{"items":[]}

...或带有项目的地图:

{"items":{"1": {...}, "2": {...}}}

如何解码它们?我尝试使用这个结构:

var response struct {
    Items map[string]Item
    Array []Item `json:"items"`
}

但它不起作用。

更新:如果(数组和对象)都会产生map[string]Item(空和已填充)

,则效果最佳

2 个答案:

答案 0 :(得分:1)

如果你需要解组为变量类型,最简单的方法是将你的出路解组为map[string]interface{}和type-assert(或者在本例中为type-switch)。

func Unmarshal(data []byte) (map[string]Item, error) {
    var d struct {
        Items interface{} `json:"items"`
    }
    if err := json.Unmarshal(data, &d); err != nil {
        return nil, err
    }
    switch dv := d.Items.(type) {
    case []interface{}:
        if len(dv) == 0 {
            return nil, nil
        }
    case map[string]interface{}:
        m := make(map[string]Item)
        for k, v := range dv {
            m[k] = Item(v)
        }
        return m, nil
    }
    // fallthrough return if different type, or non-empty array
    // Could have put this in a default case, but this catches non-empty arrays too
    return nil, fmt.Errorf("unexpected type in json")
}

以下示例显示它适用于您提供的两个示例:https://play.golang.org/p/c0oZX2-xpN

答案 1 :(得分:0)

试试这个工作代码(A):

package main

import (
    "encoding/json"
    "fmt"
)

type Item int

type response struct {
    Items map[string]Item `json:"Items"`
    Array []Item          `json:"Array"`
}

func main() {
    var d response
    err := json.Unmarshal([]byte(`{"Items":{"A":1,"B":2,"C":3},"Array":[]}`), &d)
    if err != nil {
        panic(err)
    }
    fmt.Println(d)
}

输出:

{map[C:3 A:1 B:2] []}

试试这个工作代码(B):

package main

import (
    "encoding/json"
    "fmt"
)

type Item int

type response struct {
    Items map[string]Item `json:"Items"`
    //Array []Item          `json:"Array"`
}

func main() {
    var d response
    err := json.Unmarshal([]byte(`{"Items":{"A":1,"B":2,"C":3},"Array":[]}`), &d)
    if err != nil {
        panic(err)
    }
    fmt.Println(d)
}

输出:

{map[C:3 A:1 B:2]} 

您可以使用json.Marshaljson.Unmarshal,就像这个工作代码(C)一样:

package main

import (
    "encoding/json"
    "fmt"
)

type Item int

type response struct {
    Items map[string]Item `json:"Items"`
    Array []Item          `json:"Array"`
}

func main() {
    var test = response{
        Items: map[string]Item{"A": 1, "B": 2, "C": 3},
        Array: []Item{},
    }
    body, err := json.Marshal(test)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(body)) // {"Items":{"A":1,"B":2,"C":3},"Array":[]}

    var d response
    err = json.Unmarshal(body, &d)
    if err != nil {
        panic(err)
    }
    fmt.Println(d)
}

输出:

{"Items":{"A":1,"B":2,"C":3},"Array":[]}
{map[A:1 B:2 C:3] []}

您可以将{"A":1,"B":2,"C":3}解散为map[A:1 B:2 C:3]"[1,2,3]"[1 2 3],就像这个工作代码(D):

package main

import (
    "encoding/json"
    "fmt"
)

type Item int

type response1 map[string]Item
type response2 []Item

func main() {
    var d response1
    err := json.Unmarshal([]byte(`{"A":1,"B":2,"C":3}`), &d)
    if err != nil {
        panic(err)
    }
    fmt.Println(d) // map[A:1 B:2 C:3]

    var d2 response2
    err2 := json.Unmarshal([]byte(`[1,2,3]`), &d2)
    if err2 != nil {
        panic(err2)
    }
    fmt.Println(d2) // [1 2 3]
}

输出:

map[A:1 B:2 C:3]
[1 2 3]