Перейти к содержимому

Как распарсить json golang

  • автор:

Помогите распарсить json файл на golang

Примеры из документации не подходят. Первым элементом представлен массив в моем json файле. Не могли бы вы предоставить мне пример кода, если вам не солжно?

5 дек 2017 в 21:09
Возможно, <"response":[. (добавлены ": )? 5 дек 2017 в 21:35

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

В документации всё описано.

type Body struct < Response []Response `json:"response"` >type Response struct < UID int64 `json:"uid"` FirstName string `json:"first_name"` // . >// . b := &Body<> err := json.Unmarshal(data, b) fmt.Println(err, b.Response[0].FirstName) 

Отслеживать
ответ дан 5 дек 2017 в 22:10
16k 3 3 золотых знака 25 25 серебряных знаков 41 41 бронзовый знак

Два отличных сервиса очень помогают

Даёте ему JSON он выдаёт вам Go структуру. Ваш пример:

type AutoGenerated struct < Response []struct < UID int `json:"uid"` FirstName string `json:"first_name"` LastName string `json:"last_name"` Sex int `json:"sex"` City int `json:"city"` PhotoMaxOrig string `json:"photo_max_orig"` Verified int `json:"verified"` >`json:"response"` > 

Понятное дело уже сами меняете имена полей на то что вам нравится.

Имя говорит само за себя. Красивый JSON выдаёт. Помогает увидеть структуру так сказать.

Отслеживать
ответ дан 6 дек 2017 в 18:24
521 4 4 серебряных знака 9 9 бронзовых знаков

  • json
  • vkontakte-api
  • golang
    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Парсинг JSON TOML YAML XML и CSV с помощью Go

Существует различные популярные форматы данных, используемых для разных целей, таких как передача данных между микросервисами, хранение файлов конфигурации, хранение и передача метаданных и т. д. В этой статье я покажу, как с помощью Go (Golang) парсить из файлов JSON, TOML, YAML, XML и CSV.

Парсинг JSON, TOML, YAML, XML и CSV помощью Go

Требования:

  • Требуется Go v1.11 или выше.
  • Умение использовать модули Go (Облегчает работу с Go).

Парсинг JSON

Для парсинга данных файла в формате JSON можно использовать пакет стандартной библиотеки Go encoding/json.

Вот пример парсинга файла в формате JSON с помощью Go:

Шпаргалка по работе с JSON в Golang

Парсинг JSON — одна из наиболее частых задач: в JSON приходят данные в REST API, конфигурационные файлы часто оформляются в виде JSON и пр.

Go предоставляют довольно удобные механизмы для этих целей расположенные в пакете «encoding/json» включающий в себя необходимые методы.

Преобразование в JSON

Преобразование простых типов ( bool , string , int )

boolVar, _ := json.Marshal(true) fmt.Println(string(boolVar)) // true intVar, _ := json.Marshal(1) fmt.Println(string(intVar)) // 1 fltVar, _ := json.Marshal(2.34) fmt.Println(string(fltVar)) // 2.34 strVar, _ := json.Marshal("something") fmt.Println(string(strVar)) // "something"

Преобразование массивов, слайсов и словарей

sliceVar1 := []string«John», «Andrew», «Robert»> sliceVar2, _ := json.Marshal(sliceVar) fmt.Println(string(sliceVar2)) // [«John», «Andrew», «Robert»] mapVar1 := map[string]string mapVar2, _ := json.Marshal(mapVar1) fmt.Println(string(mapVar2)) //

Преобразование пользовательских типов данных

type User struct < FirstName string LastName string Books: []string >userVar1 := &User< FirstName: "John", LastName: "Smith", Books: []string< "The Art of Programming", "Golang for Dummies" >> userVar2, _ := json.Marshal(userVar1) fmt.Println(string(userVar2)) //

По-умолчанию ключи в JSON будут соответствовать именам свойств структуры ( FirstName , LastName , Books ), если требуется изменить это поведение, то необходимо добавить теги:

type User2 struct < FirstName string `json:"name"` // свойство FirstName будет преобразовано в ключ "name" LastName string `json:"lastname"` // свойство LastName будет преобразовано в ключ "lastname" Books []string `json:"ordered_books"` // свойство Books будет преобразовано в ключ "ordered_books" >userVar3 := &User2< FirstName: "John", LastName: "Smith", Books: []string< "The Art of Programming", "Golang for Dummies" >> userVar4, _ := json.Marshal(userVar3) fmt.Println(string(userVar4)) //

Преобразование из JSON

Стандартные типы

byt := []byte(``) var dat map[string]interface<> if err := json.Unmarshal(byt, &dat); err != nil < panic(err) >fmt.Println(dat)

В dat получим объект типа map[string]interface<> . Для того, чтобы работать с «внутренностями» этого объекта придётся немного поcastовать:

num := dat["num"].(float64) // для того, чтобы получить из свойства num число fmt.Println(num) strs := dat["strs"].([]interface<>) // для того, чтобы получить массив интерфейсов. str1 := strs[0].(string) // . и потом получить из него строку fmt.Println(str1)

Пользовательские типы

Пользовательские типы так же просто можно получить из JSON:

user := User1<> userJson := "<\"FirstName\":\"John\",\"LastName\":\"Smith\",\"Books\":[\"The Art of Programming\",\"Golang for Dummies\"]>" bytes := []byte(userJson) json.Unmarshal(bytes, &user) fmt.Println(user.FirstName, user.LastName, user.Books) // John Smith [The Art of Programming Golang for Dummies] 

Но что же делать, если ключи в JSON отличаются от свойств в структуре или необходимо получать не все данные из JSON? Для этого необходимо воспользоваться знакомыми по предыдущим примерам тегами json :

user2 := User2<> userJson2 := "<\"name\":\"John\",\"lastname\":\"Smith\",\"ordered_books\":[\"The Art of Programming\",\"Golang for Dummies\"]>" bytes2 := []byte(userJson2) json.Unmarshal(bytes2, &user2) fmt.Println(user2.FirstName, user2.LastName, user2.Books) // John Smith [The Art of Programming Golang for Dummies]

Получили результат аналогичный предыдущему.

На этом основы работы с JSON можно и завершить. Поиграться с преобразование можно в Go Playground. Примеры из статьи можно найти там же.

Список полезных ссылок:

  • Go by Example: JSON
  • Go Docs. Package json
  • Unmarshaling nested JSON objects in Golang
  • The Go Blog: JSON and Go

Golang

JSON (JavaScript Object Notation) — это простой формат обмена данными. Синтаксически это напоминает объекты и списки JavaScript. Он чаще всего используется для связи между веб-интерфейсами и программами JavaScript, работающими в браузере, но также используется и во многих других местах. Его домашняя страница, json.org, предоставляет четкое и краткое определение стандарта.

С пакетом json легко и быстро читать и записывать данные JSON из ваших программ Go.

Кодирование

Для кодирования данных в JSON используется функция Marshal.

func Marshal(v interface<>) ([]byte, error)

Задав структуру данных Go, Message,

type Message struct

и экземпляр сообщения

m := Message

мы можем получить JSON-кодированную версию m, используя json.Marshal:

b, err := json.Marshal(m)

Если все хорошо, err будет nil, а b будет []byte, содержащим JSON данные:

b == []byte(``)

Будут закодированы только структуры данных, которые могут быть представлены валидным JSON:

  • Объекты JSON поддерживают только строки в качестве ключей; чтобы кодировать Go тип map он должен иметь вид map[string]T (где T — любой тип Go, поддерживаемый пакетом json).
  • Channel, complex и func типы не могут быть закодированы.
  • Циклические структуры данных не поддерживаются; они приведут к попаданию Marshal в бесконечный цикл.
  • Указатели будут закодированы как значения, на которые они указывают (или ‘null’, если указатель равен nil).

Пакет json обращается только к экспортированным полям struct типов (те, которые начинаются с заглавной буквы). Поэтому в выводе JSON будут присутствовать только экспортированные поля структуры.

Декодирование

Для декодирования JSON данных используем функцию Unmarshal.

func Unmarshal(data []byte, v interface<>) error

Сначала нужно создать место, где будут храниться декодированные данные

var m Message

и вызвать json.Unmarshal, передав ему []byte JSON данных и указатель на m

err := json.Unmarshal(b, &m)

Если b содержит допустимый JSON, который соответствует m, после вызова err будет nil и данные из b будут сохранены в структуре m, как если бы это было сделано с помощью присваивания, подобного следующему:

m = Message

Как Unmarshal идентифицирует поля для хранения декодированных данных? Для заданного ключа JSON «Foo» Unmarshal просматривает поля структуры назначения, чтобы найти (в порядке предпочтения):

  • Экспортированное поле с тегом «Foo»
  • Экспортированное поле с именем «Foo»
  • Экспортированное поле с именем «FOO» или «FoO» или другое нечувствительное к регистру совпадение «Foo»

Что происходит, когда структура данных JSON не совсем соответствует типу Go?

b := []byte(``) var m Message err := json.Unmarshal(b, &m)

Unmarshal будет декодировать только те поля, которые он может найти в типе назначения. В этом случае будет заполнено только поле Name в m, а поле Food будет игнорироваться. Это поведение особенно полезно, когда вы хотите выбрать только несколько определенных полей из большого JSON-объекта. Это также означает, что Unmarshal не затронет любые неэкспортированные поля в структуре назначения.

Но что, если вы заранее не знаете структуру данных JSON?

Универсальный JSON с interface<>

Тип interface<> (пустой интерфейс) описывает интерфейс с нулевыми методами. Каждый тип Go реализует как минимум ноль методов и поэтому удовлетворяет пустому интерфейсу.

Пустой интерфейс служит общим типом контейнера:

var i interface<> i = "a string" i = 2011 i = 2.777

Утверждение типа обращается к подлежащему конкретному типу:

r := i.(float64) fmt.Println("the circle's area", math.Pi*r*r)

Или, если базовый тип неизвестен, переключатель типа определяет тип:

switch v := i.(type) < case int: fmt.Println("twice i is", v*2) case float64: fmt.Println("the reciprocal of i is", 1/v) case string: h := len(v) / 2 fmt.Println("i swapped by halves is", v[h:]+v[:h]) default: // i ни один из типов выше >

Пакет json использует значения map[string]interface<> и []interface<> для хранения произвольных объектов и массивов JSON; он с радостью разархивирует любой допустимый большой бинарный объект JSON (blob) в простое значение interface<>. Конкретные типы Go по умолчанию:

  • bool для логических выражений JSON
  • float64 для JSON чисел
  • string для JSON строк
  • nil для JSON null
Декодирование произвольных данных

Рассмотрим JSON данные, хранящиеся в переменной b:

b := []byte(``)

Не зная структуры этих данных, мы можем декодировать их в значение interface<> с помощью Unmarshal:

var f interface<> err := json.Unmarshal(b, &f)

В этот момент значением Go в f будет карта, ключи которой являются строками, а сами значения хранятся как пустые значения интерфейса:

f = map[string]interface<>< "Name": "Wednesday", "Age": 6, "Parents": []interface<>< "Gomez", "Morticia", >, >

Чтобы получить доступ к этим данным, мы можем использовать утверждение типа для доступа к подлежащему map[string]interface<>:

m := f.(map[string]interface<>)

Затем мы можем перебрать карту с помощью оператора range и использовать переключатель типа для доступа к ее значениям в качестве их конкретных типов:

for k, v := range m < switch vv := v.(type) < case string: fmt.Println(k, "is string", vv) case float64: fmt.Println(k, "is float64", vv) case []interface<>: fmt.Println(k, "is an array:") for i, u := range vv < fmt.Println(i, u) >default: fmt.Println(k, "is of a type I don't know how to handle") > >

Таким образом, вы можете работать с неизвестными JSON данными, сохраняя при этом преимущества безопасности типов.

Ссылочные типы

Определим тип Go, который будет содержать данные из предыдущего примера:

type FamilyMember struct < Name string Age int Parents []string >var m FamilyMember err := json.Unmarshal(b, &m)

Демонстрация этих данных в значение FamilyMember работает, как и ожидалось, но если мы посмотрим внимательнее, то увидим, что произошла замечательная вещь. С помощью оператора var мы выделили структуру FamilyMember, а затем предоставили указатель на это значение для Unmarshal, но в то время поле Parents было нулевым значением среза. Чтобы заполнить поле Parents, Unmarshal выделил новый срез за кулисами. Это типично для того, как Unmarshal работает с поддерживаемыми ссылочными типами (указатели, срезы и карты).

Рассмотрим конвертирование в эту структуру данных:

type Foo struct

Если бы в объекте JSON было поле Bar, Unmarshal выделил бы новый Bar и заполнил его. Если нет, Bar будет оставлен как нулевой указатель.

Из этого вытекает полезный шаблон: если у вас есть приложение, которое получает несколько различных типов сообщений, вы можете определить структуру «получателя», например:

type IncomingMessage struct

и отправляющая сторона может заполнить поле Cmd и/или поле Msg объекта JSON верхнего уровня, в зависимости от типа сообщения, которое они хотят передать. Unmarshal при декодировании JSON в структуру IncomingMessage будет выделять только структуры данных, присутствующие в JSON данных. Чтобы узнать, какие сообщения обрабатывать, программисту просто нужно проверить, что Cmd или Msg не ноль.

Потоковые кодировщики и декодеры

Пакет json предоставляет типы Decoder и Encoder для поддержки обычной операции чтения и записи потоков данных JSON. Функции NewDecoder и NewEncoder оборачивают типы интерфейсов io.Reader и io.Writer.

func NewDecoder(r io.Reader) *Decoder func NewEncoder(w io.Writer) *Encoder

Вот пример программы, которая читает серию объектов JSON из стандартного ввода, удаляет все, кроме поля Name, из каждого объекта, а затем записывает объекты в стандартный вывод:

package main import ( "encoding/json" "log" "os" ) func main() < dec := json.NewDecoder(os.Stdin) enc := json.NewEncoder(os.Stdout) for < var v map[string]interface<>if err := dec.Decode(&v); err != nil < log.Println(err) return >for k := range v < if k != "Name" < delete(v, k) >> if err := enc.Encode(&v); err != nil < log.Println(err) >> >

Из-за повсеместного распространения программ чтения и записи эти типы кодировщиков и декодеров могут использоваться в широком диапазоне сценариев, таких как чтение и запись в соединения HTTP, веб-сокеты или файлы.

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

Использование тегов в структуре кодируемой в JSON позволяет получить названия полей в результирующем JSON, отличающиеся от названия полей в структуре. В следующем примере в результирующем JSON поле BrandID будет выглядеть как brand_id:

package main import ( "encoding/json" "fmt" ) type Item struct < ID uint `json:"id"` Title string `json:"title"` BrandID uint `json:"brand_id"` >func main() < item := Itemjitem, err := json.Marshal(item) if err != nil < fmt.Println(err.Error()) return >fmt.Println(string(jitem)) >
  • Основы Go: структуры (struct)
  • Основы Go: карты (словари)
  • Основы Go: switch с типами

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *