Помогите распарсить 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 с типами