英文:
Unmarshal json.RawMessage to a reflected slice
问题
在最后一部分,你遇到了一个异常的原因是你试图将json.RawMessage
字段解析为一个reflect.Value
类型的Go值,但是json.Unmarshal
函数无法直接将数组解析为reflect.Value
类型。
为了解决这个问题,你可以使用json.Unmarshal
函数将json.RawMessage
解析为一个临时的切片,然后使用反射将切片的元素逐个添加到reflect.Value
类型的切片中。下面是修改后的代码:
// ...
// 创建一个临时的切片用于解析json.RawMessage
var tempSlice []json.RawMessage
err = json.Unmarshal(command.Items, &tempSlice)
if err != nil {
log.Fatalln("error:", err)
}
// 使用反射将切片的元素逐个添加到reflect.Value类型的切片中
for _, item := range tempSlice {
newItem := reflect.New(itemtyp).Interface()
err = json.Unmarshal(item, newItem)
if err != nil {
log.Fatalln("error:", err)
}
rv = reflect.Append(rv, reflect.ValueOf(newItem).Elem())
}
// ...
这样修改后,你就可以成功解析json.RawMessage
字段并将其转换为reflect.Value
类型的切片了。
英文:
In the following sample, i am trying to Unmarshal
a json.RawMessage
into a slice using reflection to figure out the type of the items in the json.RawMessage
, the json.RawMessage
always represents an array of a specific type, the name of the type is included in the json and a pointer to it is retrieved from a map[string]interface{}
type command struct {
Action *string
Type *string
Items json.RawMessage //because i need to figure out the Type field value first, its always an array of a single type
}
//a sample model
type Chicken struct {
Id *int
Name *string
EggColor *string
}
//this map contains a pointer to each needed struct using reflection i can get the type and make a SliceOf it
var ModelRegistery map[string]interface {}
func main(){
//register the Chicken type to retrieve a pointer to it using a string key
var chickenPtr *Chicken
ModelRegistery = make(map[string]interface {})
ModelRegistery["Chicken"] = chickenPtr
//some json for testing
cJson := []byte(`{"Action":"BURN",
"Type":"Chicken",
"Items":[{"Id":1,"Name":"B","EggColor":"D"},
{"Id":2,"Name":"M","EggColor":"C"}]}`)
var command command
err := json.Unmarshal(cJson,&command)
if err != nil {
log.Fatalln("error:", err)
}
//get the type from the model registry and reflect it
itemtyp := reflect.TypeOf(ModelRegistery[(*command.Type)]).Elem()
//create a slice of the type
itemslice := reflect.SliceOf(itemtyp)
rv := reflect.MakeSlice(itemslice, 0, 2)
//now when trying to unmarshal the json.RawMessage field i get an exception
err = json.Unmarshal(command.Items,&rv)
if err != nil {
log.Fatalln("error:", err) //error: json: cannot unmarshal array into Go value of type reflect.Value
}
}
the question is, what am i doing wrong in the last part? why do i get the exception?
json: cannot unmarshal array into Go value of type reflect.Value
here is a goplay
http://play.golang.org/p/63dxgnPFz_
答案1
得分: 3
你需要将interface{}
传递给unmarshal函数,而不是reflect.Value。
更改以下部分似乎可以解决问题:
itemslice := reflect.SliceOf(itemtyp)
rv := reflect.New(itemslice)
//现在尝试对json.RawMessage字段进行解组时会出现异常
err = json.Unmarshal(command.Items, rv.Interface())
英文:
You need to pass interface{}
to the unmarhsal function, not a reflect.Value.
Changing the following seems to work:
itemslice := reflect.SliceOf(itemtyp)
rv := reflect.New(itemslice)
//now when trying to unmarshal the json.RawMessage field i get an exception
err = json.Unmarshal(command.Items, rv.Interface())
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论