如何将json解组为[] Person?

时间:2018-04-08 04:42:16

标签: go

我正在尝试动态设置interface {}类型的字段。在下面的所有情况下,json解组成正确的结构,但在"问题"如果json unmarshals to [] interface {}。对于那种情况,我期待[]人。为什么我的#34;问题"?

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type Employees struct {
    Indicator string      `json:"indicator"`
    Items     interface{} `json:"items"`
}

type Person struct {
    Name string `json:"name"`
}

func main() {
    simple()
    easy()
    moreDifficult()
    problem()
}

var j = []byte(`{"name": "bob"}`)
var jj = []byte(`[{"name": "bob"}, {"name": "jim"}, {"name": "fred"}]`)


func simple() {
    p := Person{}
    if err := json.Unmarshal(j, &p); err != nil {
        fmt.Println(err)
    }
    fmt.Println("easy:", p, reflect.TypeOf(p))
}

func easy() {
    p := []Person{}
    if err := json.Unmarshal(jj, &p); err != nil {
        fmt.Println(err)
    }
    fmt.Println("easy:", p, reflect.TypeOf(p))
}

func moreDifficult() {
    var j = []byte(`{"indicator": "more difficult"}`)

    e := Employees{}
    if err := json.Unmarshal(j, &e); err != nil {
        fmt.Println(err)
    }
    fmt.Println("moreDifficult", e.Items, reflect.TypeOf(e.Items))
}

func problem() {
    var j = []byte(`{"indicator:": "problem"}`)

    e := Employees{}
    if err := json.Unmarshal(j, &e); err != nil {
        fmt.Println(err)
    }
    fmt.Println("problem:", e.Items, reflect.TypeOf(e.Items)) // why not []Person???
}


func (e *Employees) UnmarshalJSON(b []byte) error {
    type alias Employees

    a := &alias{}

    if err := json.Unmarshal(b, &a); err != nil {
        return err
    }

    e.Indicator = a.Indicator

    var k = jj

    if e.Indicator == "more difficult" {
        k = j
        e.Items = &Person{}
    } else {
        e.Items = []Person{}
    }

    return json.Unmarshal(k, &e.Items)
}

https://play.golang.org/p/xQvjMyLTk5i

2 个答案:

答案 0 :(得分:1)

问题是接口的基础值不是指针:

e.Items = []Person{}

虽然您确实传递了指向接口本身的指针:

json.Unmarshal(k, &e.Items)

这不能解决基础值是非指针的问题。

var a interface{} = &T{}

var b interface{} = T{}
b = &b

ab的类型是不同的,并且将由解组器以不同的方式处理,在b的情况下,解组者将选择将指向的值替换为map[string]interface{}

因此,为了解决您的问题,您可以执行以下操作:

if e.Indicator == "more difficult" {
    k = j
    e.Items = &Person{}
} else {
    e.Items = &[]Person{}
}

return json.Unmarshal(k, e.Items)

答案 1 :(得分:0)

您当前的问题与JSON解组完全无关。

您将Items定义为interface{}类型,因此很明显,当您检查它时,它将是interface{}类型。如果您希望它是[]Person类型,只需将其定义为:

type Employees struct {
    Indicator string   `json:"indicator"`
    Items     []Person `json:"items"`
}

完成后,您的测试用例将产生预期结果。但是您的Items仍为空,因为您的输入JSON没有items字段。