json.Unmarshal with reflect

1,534 views
Skip to first unread message

Mad Go

unread,
Sep 8, 2010, 11:26:53 AM9/8/10
to golang-nuts
Hi,
I tried to convert http.Req.Form to struct, the code is pasted in
http://pastie.org/1145974, what I want is:
if typ is a *reflect.StructType, then convert the json string to
struct

type menu_S struct{
Id int
Name string
Type string
Area string
//Materials []material_S
Materials material_S
Method string
}
type material_S struct{
Food_name string
Amount int
Unit string
}

I want to convert the json string
{"Food_name":"aaa","Amount":"123","Unit":"g"} to material_S
......
case *reflect.StructType:
bs := bytes.NewBufferString(firstStrValue).Bytes()
val := reflect.MakeZero(field.Type)
fmt.Println(reflect.Typeof(val),reflect.Typeof(&val))
if err := json.Unmarshal(bs, val.Interface()); err != nil {
return os.NewError(fmt.Sprintf("Convert "+firstStrValue+" to
"+keyName+" error: %s",err))
}
sValue.FieldByName(keyName).(*reflect.StructValue).Set(val.
(*reflect.StructValue))


But I got error:json: Unmarshal(non-pointer main.material_S).
What should I do?



Steven

unread,
Sep 8, 2010, 4:50:52 PM9/8/10
to Mad Go, golang-nuts
You need to pass a struct pointer to Unmarshal, not a struct. Unfortunately, there is not way to get a pointer to a struct of arbitrary type.

BTW, this is way more complex than it needs to be. You don't need a pointer to the map (maps are already pointers), you don't need to reflect on the map at all, since you know its type statically.

I think what you could do is convert the map manually into json format. You'd still have to use reflection to scan the struct in order to determine the correct types of the fields, so that you get the formatting right. Then you could unmarshal that data directly into s.

Steven

unread,
Sep 8, 2010, 5:14:39 PM9/8/10
to Mad Go, golang-nuts
As an added note: if you find the idea of creating properly formatted json from the map daunting, you could do exactly what you're doing right now, but instead of assigning values to the fields of the `sValue`, you could instead assign them to a `map[string] interface{}`, and unpack structs into `map[string] interface{}`s. Then you could marshal this, and then unmarshal it into `s`.

Steven

unread,
Sep 9, 2010, 2:27:28 PM9/9/10
to Mad Go, golang-nuts

It just occured to me that you could umarshal struct fields to a
'map[string] interface{}', then copy the fields manually from the map
to the struct field. This would probably be simpler than my other
suggestions.

Sorry for the spam. There are a lot of ways you could approach this
problem, and I keep thinking of new ones that may be more
straightforward, or better fit your needs :)

Reply all
Reply to author
Forward
0 new messages