Personalizando a desempacotamento de JSON com reflexão
No Go, desempacotar JSON em uma estrutura é um processo direto. No entanto, ao lidar com campos que possuem tags personalizadas, como json:"some_field", o mecanismo de desempacotamento padrão pode não ser suficiente.
Uma abordagem para lidar com esse cenário é usar reflexão. Ao inspecionar os campos da estrutura usando reflexão, podemos verificar se um campo tem uma tag específica e, em caso afirmativo, lidar com sua desempacotamento de acordo.
Neste caso específico, queremos garantir que um campo com a tag json seja desempacotado em um campo de string como está. Isso nos permite lidar com objetos JSON ou matrizes dentro de nossa estrutura Go.
Cenário de exemplo
Considere os seguintes dados JSON e estrutura Go:
{
"I": 3,
"S": {
"phone": {
"sales": "2223334444"
}
}
}
type A struct {
I int64
S string `sql:"type:json"`
}
Nosso objetivo é desempacotar o campo "S" como uma string, preservando sua estrutura JSON aninhada.
Solução usando reflexão
O seguinte o código demonstra como conseguir isso usando reflexão:
func main() {
a := A{}
// Unmarshal the JSON data into a byte slice
var data []byte
// Iterate over the fields of the struct
typ := reflect.TypeOf(a)
val := reflect.ValueOf(a)
for i := 0; i Nesta abordagem, inspecionamos manualmente cada campo da estrutura usando reflexão para determinar se ele possui a tag "json". Nesse caso, desempacotamos os dados JSON no campo como uma string.
Solução alternativa com Custom Marshaler e Unmarshaler
Outra opção é implementar um tipo personalizado, como RawString, que implementa as interfaces json.Marshaler e json.Unmarshaler. Isso permite mais flexibilidade e controle sobre o processo de desempacotamento.
Essa abordagem é demonstrada no código a seguir:
// RawString is a raw encoded JSON object.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawString string
// MarshalJSON returns *m as the JSON encoding of m.
func (m *RawString) MarshalJSON() ([]byte, error) {
return []byte(*m), nil
}
// UnmarshalJSON sets *m to a copy of data.
func (m *RawString) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("RawString: UnmarshalJSON on nil pointer")
}
*m = RawString(data)
return nil
}
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S RawString `sql:"type:json"`
}
func main() {
a := A{}
err := json.Unmarshal([]byte(data), &a)
if err != nil {
log.Fatal("Unmarshal failed", err)
}
fmt.Println("Done", a)
}
Ao implementar nosso próprio tipo, podemos personalizar o processo de desempacotamento e evitar a necessidade de reflexão, resultando em uma solução mais limpa e eficiente.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3