代码之家  ›  专栏  ›  技术社区  ›  divflex

动态创建某种类型的结构并将JSON解包到该实例中

  •  2
  • divflex  · 技术社区  · 6 年前

    我正在运行时创建结构实例。该实例已成功创建,但我无法将JSON解组到其中。

    type Test struct {
        Name string `json:"name,omitempty"`
    }
    
    func create(a interface{}) {
        aType := reflect.TypeOf(a).Elem()
        elType := aType.Elem()
    
        f := reflect.Indirect(reflect.New(elType))
    
        b := []byte(`{"name": "go"}`)
    
        err := json.Unmarshal(b, &f)
        fmt.Println(err, f)
    }
    
    func main() {
        l := []Test{}
        create(&l)
    }
    
    3 回复  |  直到 6 年前
        1
  •  3
  •   icza    6 年前

    reflect.Indirect() 返回类型的值 reflect.Value ,您应该将指针传递给 Test (类型为 *Test )至 json.Unmarshal() .

    只需使用 Value.Interface() 方法获取指向 测试 结构返回者 reflect.New() ,如下所示:

    f := reflect.New(elType).Interface()
    b := []byte(`{"name": "go"}`)
    err := json.Unmarshal(b, f)
    

    这样,它就可以工作,输出将是:

    <nil> &{go}
    

    注意 f 将属于 interface{} 类型,保持 *测试 指针值。如果需要结构值,可以使用类型断言,如下所示:

    t := *f.(*Test)
    fmt.Println(t)
    

    打印内容:

    {go}
    

    尝试上的示例 Go Playground .

        2
  •  3
  •   Mazdak    6 年前

    我认为您不需要使用Reflect,而是可以执行以下操作:

    type Test struct {
        Name string `json:"name,omitempty"`
    }
    
    func create(a interface{}) {
        b := []byte(`[{"name": "go"}]`)
    
        err := json.Unmarshal(b, &a)
        fmt.Println(err, a)
    }
    
    func main() {
        l := []Test{}
        create(&l)
    }
    
        3
  •  2
  •   leaf bebop    6 年前

    代码 reflect.Indirect(reflect.New(elType)) 返回 reflect.Value 而不是 elType .当您取消标记时,json包会查看 反映价值 没有字段的结构 Name 所以它什么也不做。

    相反,你应该使用 reflect.Value.Interface() 把它变成 interface{} 保持混凝土类型。

    操场: https://play.golang.org/p/sW9mJd8fKMb