Генери c демаршаллинг в Go - PullRequest
       107

Генери c демаршаллинг в Go

0 голосов
/ 05 августа 2020

Я пытаюсь выяснить, есть ли способ демаршалировать JSON строки в определенную c структуру, используя только строку и предполагаемый тип. Вот что я придумал до сих пор.

Код

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?

1 Ответ

2 голосов
/ 05 августа 2020

Вы можете сравнивать указатели людей, потому что reflect.DeepEqual() также принимает, если указанные значения (глубоко) равны:

Значения указателя глубоко равны, если они равны, используя Go 's == operator или если они указывают на глубоко равные значения .

Так что просто выполните:

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

Оба отпечатка true (попробуйте на Go игровой площадке ):

are variables equal: true
are variables equal: true

Также обратите внимание, что для вашей «простой» структуры вы можете использовать простое == сравнение:

*unmarshalledPerson.(*Person) == person

Этого не будет, если вы добавите другие поля, такие как указатели, структуры , maps et c.

...