I'm trying to figure out if there is a way to unmarshal JSON strings to a specific struct, using only the string and the intended type. Here is what I have come up with so far.
Code
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name"`
}
func genericUnmarshal(jsonString string, t reflect.Type) interface{} {
p := reflect.New(t)
result := p.Interface()
json.Unmarshal([]byte(jsonString), &result)
return result
}
func main() {
jsonData := "{\"name\":\"John\"}"
unmarshalledPerson := genericUnmarshal(jsonData, reflect.TypeOf(Person{}))
person := Person{Name: "John"}
fmt.Printf("struct value: %+v type: %+v\n", person, reflect.TypeOf(person))
fmt.Printf("unmarshalled value: %+v type: %+v\n", unmarshalledPerson, reflect.TypeOf(unmarshalledPerson))
fmt.Printf("are variables equal: %v\n", reflect.DeepEqual(unmarshalledPerson, person))
}
Returns
struct value: {Name:John} type: main.Person
unmarshalled value: &{Name:John} type: *main.Person
are variables equal: false
The method genericUnmarshal
returns a pointer to the type.
My question: Is there a way change the unmarshalled value into a struct (i.e. Person
) instead of a pointer, so that reflect.DeepEqual(unmarshalledPerson, person)
returns true
?
You may compare person pointers, because reflect.DeepEqual()
also accepts if the pointed values are (deeply) equal:
Pointer values are deeply equal if they are equal using Go's == operator or if they point to deeply equal values.
So simply do:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(unmarshalledPerson, &person))
Or dereference the *Person
pointer wrapped inside unmarshalledPerson
so you get a Person
struct:
fmt.Printf("are variables equal: %v\n",
reflect.DeepEqual(*unmarshalledPerson.(*Person), person))
Both prints true
(try it on the Go Playground):
are variables equal: true
are variables equal: true
Also note that for your "simple" struct you may use simple ==
comparison:
*unmarshalledPerson.(*Person) == person
This won't be the case if you add other fields such as pointers, structs, maps etc.