Настройка демаршалинга 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