Обработка JSON с помощью Go

Основы маршалинга и демаршалинга JSON

JSON означаетJavaScriptНотация объектов, и это очень удобный способ обмена структурированными данными. И это очень популярно, особенно при взаимодействии с API.

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

По сравнению со слабо типизированными языками декодирование JSON сложнее. В JavaScript все, что вам нужно сделать, этоJSON.parse(). Python имеетjson.loads(), а в PHP естьjson_decode(). Они просто сбрасывают значения без проблем, но, поскольку Go строго типизирован, вам нужно проделать немного больше работы, чтобы сопоставить типы.

JSON имеет 3 основных типа:булевы,числа,струны, в сочетании с использованиеммассивыиобъектыстроить сложные конструкции.

Терминологические вызовы Goмаршалпроцесс генерации строки JSON из структуры данных, идемаршалакт синтаксического анализа JSON в структуру данных.

Строка JSON

input := `{"firstname": "Bill", "surname": "Gates"}`

Unmarshal JSON

Вот пример JSON, взятый изMDN Mozilla

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": [
        "Radiation resistance",
        "Turning tiny",
        "Radiation blast"
      ]
    },
    {
      "name": "Madame Uppercut",
      "age": 39,
      "secretIdentity": "Jane Wilson",
      "powers": [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name": "Eternal Flame",
      "age": 1000000,
      "secretIdentity": "Unknown",
      "powers": [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}

Как мы можем преобразовать его в структуру данных Go? Конечно, нам нужна соответствующая структура данных. У нас есть 5 основных типов и массив объектов. Начнем с основных типов:

type squad struct {
    SquadName string
    HomeTown string
    Formed int
    SecretBase string
    Active bool
}

Нам нужно определить JSON как[]byte, так:

input := []byte(`
    {
        "squadName": "Super hero squad",
        [...]
    }
`)

И мы можем демаршалировать JSON в экземпляр отряда:

s := squad{}
err := json.Unmarshal(input, &s)
if err != nil {
    panic(err)
}
fmt.Printf("%v", s)

Это напечатает

{Super hero squad Metro City 2016 Super tower true}

играть в

Обратите внимание, что у нас нет ошибок, связанных с отсутствием соответствия между значениями JSON и нашей структурой, они игнорируются.

Давайте удостоверимся, что json.Unmarshal () получит все поля:

type squad struct {
	SquadName  string
	HomeTown   string
	Formed     int
	SecretBase string
	Active     bool
	Members    []Member
}

type Member struct { Name string Age int SecretIdentity string Powers []string }

играть в

Не забудьте, что в ваших структурах должны быть публичные (прописные) свойства.

Переименование имен полей JSON

В этом случае все было хорошо, потому что у JSON были совместимые имена файлов. Что, если вы хотите сопоставить JSON с другими полями в вашей структуре?

Например, что, если имя участника передается какmember_name, но вы хотите, чтобы он хранился вNameвместо?

Используйте этот синтаксис:

type Member struct {
	Name string `json:"member_name"`
}

Игнорирование полей JSON

Используйте этот синтаксис:

type Member struct {
	Name string `json:"-"`
}

и поле Name будут игнорироваться при маршалинге / демаршалинге.

Преобразование типов полей JSON

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

type Member struct {
    Age       int `json:"age,string"`
}

Структура члена имеетAgeсобственность, представленная какint. Что, если вы хотите, чтобы это былstringвместо этого, но JSON передаетint?

Используйте аннотацию типа:

type Member struct {
    Age       json.Number `json:"age,Number"`
}

Тип Number - это псевдоним дляstring.

Узнайте больше о тегах вОбъяснение тегов Go

Маршал JSON

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

package main

import ( “encoding/json” “fmt” )

type country struct { Name string }

func main() { country_code := “US”

<span style="color:#a6e22e">the_country</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">country</span>{}

<span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">country_code</span> {
<span style="color:#66d9ef">case</span> <span style="color:#e6db74">"US"</span>:
	<span style="color:#a6e22e">the_country</span>.<span style="color:#a6e22e">Name</span> = <span style="color:#e6db74">"United States"</span>
}

<span style="color:#a6e22e">c</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Marshal</span>(<span style="color:#a6e22e">the_country</span>)
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
	panic(<span style="color:#a6e22e">err</span>)
}

<span style="color:#75715e">// c is now a []byte containing the encoded JSON

fmt.Print(string(c)) }

играть в

При выполнении эта программа напечатает{"Name":"United States"}.

json.Marshal()возвращает[]byte, поэтому мы должны преобразовать его в строку при передаче вfmt.Print(), в противном случае вы увидите список явно бессмысленных чисел (но они имеют смысл, поскольку являются фактическими байтами, составляющими строку).

json.Marshal()будет правильно обрабатывать базовые и композитные типы, такие как срезы и карты.

Прочитайте больше

Прочитайте большев блоге GoИ ввencoding/jsonпакет документов


Больше руководств по go: