如何将 json 取消编组为 [] 人

  • 本文关键字:取消编组 json go
  • 更新时间 :
  • 英文 :


我正在尝试动态设置接口{}类型的字段。在下面的所有情况下,json 解组到正确的结构中,但在"问题"情况下,json 解组到 []interface{}。对于这种情况,我期待[]人。为什么我得到错误的"问题"类型?

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

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

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)

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

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

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

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

最新更新