0

我试图弄清楚是否有一种方法可以仅使用字符串和预期类型将 JSON 字符串解组为特定结构。到目前为止,这是我想出的。

代码

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

退货

struct value: {Name:John} type: main.Person
unmarshalled value: &{Name:John} type: *main.Person
are variables equal: false

该方法genericUnmarshal返回一个指向该类型的指针。

我的问题:有没有办法将未编组的值更改为结构(即Person)而不是指针,以便reflect.DeepEqual(unmarshalledPerson, person)返回true

4

1 回答 1

2

您可以比较人员指针,因为reflect.DeepEqual()如果指向的值(深度)相等,也可以接受:

如果指针值使用 Go 的 == 运算符相等,或者它们指向深度相等的值,则它们是深度相等的。

所以只需这样做:

fmt.Printf("are variables equal: %v\n",
    reflect.DeepEqual(unmarshalledPerson, &person))

或者取消引用*Person包裹在里面的指针,unmarshalledPerson这样你就得到了一个Person结构:

fmt.Printf("are variables equal: %v\n",
    reflect.DeepEqual(*unmarshalledPerson.(*Person), person))

两张照片(在Go Playgroundtrue上试试):

are variables equal: true
are variables equal: true

另请注意,对于您的“简单”结构,您可以使用简单的==比较:

*unmarshalledPerson.(*Person) == person

如果您添加其他字段(例如指针、结构、映射等),则不会出现这种情况。

于 2020-08-05T10:33:14.173 回答