反射值上的解组

huangapple go评论78阅读模式
英文:

Unmarshal on reflected value

问题

这是代码:

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函数中,无法将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"},我需要从Unmarshal中获取user对象。诀窍在于反射,但我不知道怎么做。

英文:

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)

}

In the Get function

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)
    }

I am unable to unmarshal the json into the underlying object type.

Whats wrong here? I am so stuck here. Something very simple yet so difficult to figure out.

Thanks

UPDATE::Goal of this problem is to retreive a fully formed object of type passed in Get function.

The approach mentioned by Nick on the comment below doesnot get me the actual object which I already tried before. I can anyways retrieve the data (even when the object has recursive objects underneath) in a map like this

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)
}

However I need the actual object back not just the data. Something like user := &User{"SomeName"} where I need user object back from Unmarshall. The trick is somewhere in reflection but dont know how.
1: http://play.golang.org/p/n0HwJld7It

答案1

得分: 5

我对你为什么要这样做感到困惑,但是这里是修复的方法:

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链接

在我看来,你似乎费了很大的劲来创建一个空的&User,而实际上你已经在b中有一个了,例如:

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

但我猜想在这个计划中可能还有一些不明显的东西!

英文:

I'm confused as to why you want to do this, but here is how to fix it

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)
}

Note the call to Interface().

Playground link

It seems to me that you are going to a lot of trouble to make an empty &User when you already have one in b, eg

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

But I'm guessing there is some more to this plan which isn't apparent here!

答案2

得分: 1

reflect.New(objType) 返回一个 reflect.Value,它与你传入的接口不同。根据 Value 的文档,它是一个只有未导出字段的结构体。json 包无法处理未导出字段。由于它不是你传入的相同对象,而且它甚至不能进行 JSON 编码/解码,所以 json 包会失败。

在尝试使用 reflect 包时,你可能会发现 Laws of Reflection 这篇文章很有用。

英文:

reflect.New(objType) returns a reflect.Value Which is not the thing as the interface you passed. According to the docs for Value It is a struct with only unexported fields. the json package can't work with unexported fields. Since it's not the same object as you passed in and it's not even json encodable/decodable the json package will fail.

You will probably find the Laws of Reflection article useful while trying to use the reflect package.

huangapple
  • 本文由 发表于 2013年8月18日 07:31:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/18294285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定