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

0
rost5000 13 Дек 2020 в 15:36

1 ответ

Лучший ответ

Unmarshal() должен изменить получателя, поэтому это должен быть указатель, см. Этот рабочий пример:

func (receiver *Mode) UnmarshalJSON(data []byte) error {
    *receiver = Mode(data[1 : len(data)-1])
    return nil
}

Будет выведено (попробуйте на Go Playground):

source:  update ; received:  update

См. Соответствующий вопрос: Как выполнить демаршаллинг json с настраиваемым типом атрибута в Go

Также вам не следует самостоятельно обрабатывать создание / синтаксический анализ string, нет гарантии, что ввод является действительным JSON string, и вы не обрабатываете правильное экранирование. Оставьте это пакету encoding/json.

Так что лучше используйте эту реализацию:

func (receiver Mode) MarshalJSON() ([]byte, error) {
    return json.Marshal(receiver.String())
}

func (receiver *Mode) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    *receiver = Mode(s)
    return nil
}

Это будет обрабатывать недопустимый ввод и всегда генерировать допустимый вывод JSON. Он выводит то же самое, попробуйте его на Go Playground.

2
icza 13 Дек 2020 в 13:24