"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Como personalizar o desempacotamento JSON com reflexão no Go?

Como personalizar o desempacotamento JSON com reflexão no Go?

Publicado em 2024-11-16
Navegar:981

How to Customize JSON Unmarshaling with Reflection in Go?

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.

Tutorial mais recente Mais>

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