Пользовательское несогласование с типом, чем ввод другого типа

# #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. Большое спасибо. Я кое-чему учусь благодаря тебе 🙂