JSON Unmarshal
Из этой темы мы узнаем:
-
Как происходит декодирование JSON.
-
Каков алгоритм обработки сложных данных и приоритеты полей.
-
Как использовать теги структуры и работать с картами.
-
Как использовать Unmarshaler и TextUnmarshaler.
-
Как работать с кодером и декодером.
Важно! Код, над которым ты будешь работать по мере прохождения темы, необходимо разместить по пути module2/stl/json/Unmarshal.
Декодирование JSON
Декодирование JSON немного сложнее, чем кодирование, потому что в ходе декодирования нужно преобразовать некоторые текстовые данные в сложную структуру данных. Чтобы декодировать JSON в допустимую структуру данных, такую как map или struct, сначала нужно убедиться, что JSON валидный.
Мы можем использовать функцию, чтобы проверить, валидный ли JSON. Эта функция возвращает значение true, если JSON валидный, и false, если не валидный.
Пришло время поработать с кодом!
В приведенной выше программе есть некоторые данные JSON, хранящиеся внутри переменной data, и мы просто используем функцию json.Valid(data), чтобы проверить, содержит ли data действительный JSON, чтобы его можно было декодировать без ошибки. Поскольку JSON, представленный выше, действителен, он возвращает true.
Так же, как мы использовали функцию json.Marshal для кодирования данных JSON из структуры данных, мы должны использовать функцию json.Unmarshal для декодирования данных JSON в структуру данных, например, map или struct.
Функция Unmarshal принимает JSON data в качестве первого аргумента и контейнер v, в котором будут храниться данные, в качестве второго аргумента. Аргумент v является либо указателем на допустимую структуру данных, либо значением на переданный интерфейс.
Если v является nil (кроме интерфейса nil) либо оказывается нессылочным типом, то Unmarshal возвращает ошибку. Он также возвращает ошибку json.InvalidUnmarshalError, если JSON не может быть преобразован в значение хранящееся в v.
Пришло время поработать с кодом!
В приведенном выше примере мы объявили простой тип структуры Student с основными полями. В функции main объект data содержит допустимые данные JSON. Некоторые имена полей в этом JSON соответствуют структуре Student.
Позже мы объявили пустую структуру в переменной john типа Student. Как и в случае с пустой структурой struct, все ее поля будут установлены в соответствующие нулевые значения, например, 0 для целых чисел и “” для строк. Затем мы использовали указатель на john внутреннюю функцию Unmarshal. Эта программа при запуске с использованием команды go run go-json.go дает следующий результат.
Как мы видим из результата, поле lastName остается пустым, потому что оно не экспортировалось, несмотря на то, что такое же поле существовало в данных JSON. Любые дополнительные поля JSON, если они не объявлены в struct, не будут демаршаллированы.
Вы также можете заметить, что поле HeightInMeters в JSON представляет собой целое число, но оно было успешно преобразовано в float64. Как мы знаем, JSON имеет тип данных number только для представления чисел, поэтому данное значение в Unmarshal будет преобразовано из number в float64.
К сожалению, обратный сценарий невозможен. Unmarshal вернет ошибку, если поле JSON содержит число с плавающей запятой и соответствующее поле обозначено как int. Следовательно, лучше обозначить числовое поле, как float32/64 в сценариях, где поле может быть либо целым числом, либо числом с плавающей запятой.
Если поле в JSON не содержит значения типа данных, объявленного в структуре, это значение в Unmarshal не будет приведено к соответствующему типу данных поля, а вместо этого будет возвращено сообщение об ошибке.