«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Как настроить демаршалинг JSON с помощью отражения в Go?

Как настроить демаршалинг JSON с помощью отражения в Go?

Опубликовано 16 ноября 2024 г.
Просматривать:294

How to Customize JSON Unmarshaling with Reflection in Go?

Настройка демаршалинга JSON с отражением

В Go демаршалинг JSON в структуру — это простой процесс. Однако при работе с полями, имеющими настраиваемые теги, например json:"some_field", стандартного механизма демаршаллинга может оказаться недостаточно.

Один из подходов к решению этого сценария — использовать отражение. Проверяя поля структуры с помощью отражения, мы можем проверить, имеет ли поле определенный тег, и если да, то соответствующим образом обработать его демаршалинг.

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

Пример сценария

Рассмотрим следующие данные JSON и структуру Go:

{
  "I": 3,
  "S": {
    "phone": {
      "sales": "2223334444"
    }
  }
}
type A struct {
    I int64
    S string `sql:"type:json"`
}

Наша цель — демаршалировать поле «S» как строку, сохранив его вложенную структуру JSON.

Решение с использованием отражения

Следующее код демонстрирует, как этого добиться с помощью отражения:

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 

При таком подходе мы вручную проверяем каждое поле структуры с помощью отражения, чтобы определить, имеет ли оно тег «json». Если это так, мы демаршалируем данные JSON в поле в виде строки.

Альтернативное решение с пользовательским маршалером и демаршалером

Другой вариант — реализовать собственный тип, например RawString, который реализует интерфейсы json.Marshaler и json.Unmarshaler. Это обеспечивает большую гибкость и контроль над процессом демаршаллинга.

Этот подход продемонстрирован в следующем коде:

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

Реализуя собственный тип, мы можем настроить процесс демаршаллинга и избежать необходимости рефлексии, что приводит к более чистому и эффективному решению.

Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3