# #go #unmarshalling
Вопрос:
Я учусь Идти, и у меня есть вопрос:
У меня есть Info
тип, который определен так:
type Info struct {
ID ID `json:"id,omitempty"`
DisplayName string `json:"display_name,omitempty"`
}
Я создал пользовательскую UnmarshallJSON
функцию, чтобы отключить эту структуру, потому что в качестве входных данных у меня есть либо:
- An
[]interface{}
с позицией [0] int и [1] строкой - A
boolean
всегда равноfalse
значению, что поле являетсяnull
Я хочу , чтобы при вводе false
информация была равна нулю.
Вот UnmarshallJSON
функция
func (i *Info) UnmarshalJSON(data []byte) error {
var v []interface{}
if err := json.Unmarshal(data, amp;v); err != nil {
var v bool
if err = json.Unmarshal(data, amp;v); err != nil {
return err
}
return nil
}
i.ID = ID(v[0].(float64))
i.DisplayName = v[1].(string)
return nil
}
Это некрасиво, и я хотел бы знать, есть ли лучший вариант.
Большое спасибо.
Комментарии:
1. Это выглядит прекрасно и делает свою работу. Обратите внимание, однако, что вы не можете установить указатель на структуру
nil
. Когда тебяUnmarshalJSON()
позовут,i
не будетnil
. Вы можете установитьi
nil
значение, но это всего лишь локальная переменная, вы не можетеnil
передать исходный указатель в качестве получателя.2. Да, я только что это увидел, я отредактировал это
3. почему ты делаешь это
i.ID = ID(v[0].(float64))
вместоi.ID = v[0].(int)
того, чтобы ? Что означает тип идентификатора ID?4. Если
ID
поле имеет типint
, оно должно бытьi.ID = int(v[0].(float64))
5. «Это некрасиво» Нет, это не так. Ваш API уродлив, и это отражается в коде.
Ответ №1:
Кулак вам следует быть более осторожным в отношении неожиданных типов и длины, чтобы избежать паники. Затем вы можете отменить выделение в a []json.RawMessage
, чтобы отложить выделение элементов до тех пор, пока вы не будете готовы. Наконец, вы должны остерегаться своего инвалида true
.
Вот мое лучшее усилие, пожалуйста, другие не стесняйтесь редактировать (вот игровая площадка):
func (i *Info) UnmarshalJSON(data []byte) error {
var raw interface{}
if err := json.Unmarshal(data, amp;raw); err != nil {
return err
}
switch r := raw.(type) {
case []interface{}:
case bool:
if r {
return errors.New("unexpected true, must be array or false")
}
return nil
default:
return fmt.Errorf("unexpected type %T, must be array or false", r)
}
var v []json.RawMessage
if err := json.Unmarshal(data, amp;v); err != nil {
return err
}
if len(v) != 2 {
return fmt.Errorf("unexpected length %d, must be 2", len(v))
}
if err := json.Unmarshal(v[0], amp;i.ID); err != nil {
return err
}
if err := json.Unmarshal(v[1], amp;i.DisplayName); err != nil {
return err
}
return nil
}
Комментарии:
1. Большое спасибо. Я кое-чему учусь благодаря тебе 🙂