【问题标题】:Unmarshal on reflected value对反射值进行解组
【发布时间】:2013-08-20 02:21:01
【问题描述】:

Here is the code

package main

import (
    "fmt"

    "encoding/json"
    "reflect"
)

var (
    datajson []byte
    //ref mapp
)

type mapp map[string]reflect.Type

type User struct {
    Name string
    //Type map[string]reflect.Type
}

func MustJSONEncode(i interface{}) []byte {
    result, err := json.Marshal(i)
    if err != nil {
        panic(err)
    }
    return result
}
func MustJSONDecode(b []byte, i interface{}) {
    err := json.Unmarshal(b, i)
    if err != nil {
        panic(err)
    }

}
func Store(a interface{}) {
    datajson = MustJSONEncode(a)
    //fmt.Println(datajson)
}

func Get(a []byte, b interface{}) {
    objType := reflect.TypeOf(b).Elem()
obj := reflect.New(objType)
//fmt.Println(obj)
MustJSONDecode(a, &obj)
fmt.Printf("%s", obj)
    }

func main() {

    dummy := &User{}
    david := User{Name: "DavidMahon"}

    Store(david)
    Get(datajson, dummy)

}

在Get函数中

func Get(a []byte, b interface{}) {
    objType := reflect.TypeOf(b).Elem()
obj := reflect.New(objType)
//fmt.Println(obj)
MustJSONDecode(a, &obj)
fmt.Printf("%s", obj)
    }

我无法将 json 解组为基础对象类型。

这里有什么问题?我被困在这里了。一些非常简单但很难弄清楚的事情。

谢谢

更新::这个问题的目标是检索在 Get 函数中传递的类型的完全形成的对象。

尼克在下面的评论中提到的方法并没有让我得到我之前已经尝试过的实际对象。我无论如何都可以在这样的地图中检索数据(即使对象下面有递归对象)

func Get(a []byte) {
    var f interface{}

    //buf := bytes.NewBuffer(a)
    //v := buf.String()
    //usr := &User{}

    MustJSONDecode(a, &f)
    fmt.Printf("\n %v \n", f)
}

但是,我需要返回实际对象而不仅仅是数据。像user := &User{"SomeName"} 这样我需要从Unmarshall 回来的user 对象。诀窍在于反思,但不知道如何。

【问题讨论】:

  • Reflect 不会像您认为的那样做。您不能使用它构造任意对象。您可能可以使用 reflect 和 unsafe 拼凑一些东西,但实际上您应该重新考虑您正在尝试做什么。
  • 谢谢我关闭这个线程。感谢您抽出时间。为你的答案 +1。

标签: json reflection go unmarshalling


【解决方案1】:

我对你为什么要这样做感到困惑,但这里是如何解决它

func Get(a []byte, b interface{}) {
    objType := reflect.TypeOf(b).Elem()
    obj := reflect.New(objType).Interface()
    //fmt.Println(obj)
    MustJSONDecode(a, &obj)
    fmt.Printf("obj = %#v\n", obj)
}

注意对Interface()的调用。

Playground link

在我看来,当您已经在b 中创建一个空的&User 时,您会很麻烦,例如

func Get(a []byte, b interface{}) {
    MustJSONDecode(a, &b)
    fmt.Printf("obj = %#v\n", b)
}

但我猜这个计划还有更多内容在这里不明显!

【讨论】:

  • 谢谢,但我已经尝试过 thsat 技巧。这有两个问题。
  • 1.它不适用于递归对象类型。即对象中的对象和2。返回的数据不是Get函数中发送的类型的对象。那是棘手的部分。我更新了我的问题以澄清这一点。
  • 返回了什么对象?你不返回一个对象。已经是正确类型的 b 通过调用 MustJSONDecode 来填充。
  • 不,不是,因为我无法访问像 obj.Name 这样的字段。它的格式不正确。如果它是正确的,那么我可以访问 obj.Name 和其他所有字段。
  • 哦,我明白你在说什么。我必须使用虚拟对象来解包数据。哇,所以基本上我所做的一切都是浪费时间。我太傻了。
【解决方案2】:

reflect.New(objType) 返回一个reflect.Value,这不是您传递的接口。根据Value 的文档,这是一个只有未导出字段的结构。 json 包不能用于未导出的字段。由于它与您传入的对象不同,而且它甚至不是 json 可编码/可解码的,因此 json 包将失败。

在尝试使用反射包时,您可能会发现Laws of Reflection 文章很有用。

【讨论】:

  • 感谢您的参考。我读了三次,但有人认为我注意到这篇文章(顺便说一句非常贴心)没有谈论从其他对象创建对象。可能是作者将其保留为开发人员自行决定的一部分。
  • 您不能真正使用反射来创建您描述的特定类型的对象。您可以使用反射来查看 if 对象是否属于特定类型,但不能构造任意类型。
猜你喜欢
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2013-06-27
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多