Поиск…


Синтаксис

  • func Маршал (v интерфейс {}) ([] байт, ошибка)
  • func Unmarshal (data [] byte, v interface {}) error

замечания

Пакет "encoding/json" Package json реализует кодирование и декодирование объектов JSON в Go .


Типы в JSON вместе со своими конкретными типами в Go:

Тип JSON Go Concrete Type
логический BOOL
чисел float64 или int
строка строка
ноль ноль

Базовая кодировка JSON

json.Marshal из пакета "encoding/json" кодирует значение JSON.

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

decodedValue := []string{"foo", "bar"}

// encode the value
data, err := json.Marshal(decodedValue)

// check if the encoding is successful
if err != nil {
    panic(err)
}

// print out the JSON-encoded string
// remember that data is a []byte
fmt.Println(string(data))
// "["foo","bar"]"

Детская площадка

Вот некоторые основные примеры кодирования для встроенных типов данных:

var data []byte

data, _ = json.Marshal(1)
fmt.Println(string(data))
// 1

data, _ = json.Marshal("1")
fmt.Println(string(data))
// "1"

data, _ = json.Marshal(true)
fmt.Println(string(data))
// true

data, _ = json.Marshal(map[string]int{"London": 18, "Rome": 30})
fmt.Println(string(data))
// {"London":18,"Rome":30}

Детская площадка

Кодирование простых переменных полезно для понимания того, как кодирование JSON работает в Go. Однако в реальном мире вы, скорее всего, кодируете более сложные данные, хранящиеся в структурах .

Базовое декодирование JSON

json.Unmarshal из пакета "encoding/json" декодирует значение JSON в значение, указанное данной переменной.

Параметры - это значение для декодирования в []bytes и переменная, используемая в качестве хранилища для де-сериализованного значения. Возвращаемое значение - ошибка (при сбое).

encodedValue := []byte(`{"London":18,"Rome":30}`)

// generic storage for the decoded JSON
var data map[string]interface{}

// decode the value into data
// notice that we must pass the pointer to data using &data
err := json.Unmarshal(encodedValue, &data)

// check if the decoding is successful
if err != nil {
    panic(err)
}

fmt.Println(data)
map[London:18 Rome:30]

Детская площадка

Обратите внимание, как в приведенном выше примере мы заранее знали тип ключа и значение. Но это не всегда так. Фактически, в большинстве случаев JSON содержит смешанные типы значений.

encodedValue := []byte(`{"city":"Rome","temperature":30}`)

// generic storage for the decoded JSON
var data map[string]interface{}

// decode the value into data
if err := json.Unmarshal(encodedValue, &data); err != nil {
    panic(err)
}

// if you want to use a specific value type, we need to cast it
temp := data["temperature"].(float64)
fmt.Println(temp) // 30
city := data["city"].(string)
fmt.Println(city) // "Rome"

Детская площадка

В последнем примере выше мы использовали общую карту для хранения декодированного значения. Мы должны использовать map[string]interface{} потому что знаем, что ключи являются строками, но мы не знаем тип их значений заранее.

Это очень простой подход, но он также крайне ограничен. В реальном мире вы обычно декодируете JSON в настраиваемый тип struct .

Декодирование данных JSON из файла

Данные JSON также могут считываться из файлов.

Предположим, у нас есть файл с именем data.json со следующим содержимым:

[
    {
      "Name" : "John Doe",
      "Standard" : 4
    },
    {
      "Name" : "Peter Parker",
      "Standard" : 11
    },
    {
      "Name" : "Bilbo Baggins",
      "Standard" : 150
    }
]

В следующем примере читается файл и декодируется содержимое:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "os"
)

type Student struct {
    Name     string
    Standard int `json:"Standard"`
}

func main() {
    // open the file pointer
    studentFile, err := os.Open("data.json")
    if err != nil {
        log.Fatal(err)
    }
    defer studentFile.Close()

    // create a new decoder
    var studentDecoder *json.Decoder = json.NewDecoder(studentFile)
    if err != nil {
        log.Fatal(err)
    }

    // initialize the storage for the decoded data
    var studentList []Student
    
    // decode the data
    err = studentDecoder.Decode(&studentList)
    if err != nil {
        log.Fatal(err)
    }

    for i, student := range studentList {
        fmt.Println("Student", i+1)
        fmt.Println("Student name:", student.Name)
        fmt.Println("Student standard:", student.Standard)
    }
}

Файл data.json должен находиться в том же каталоге исполняемой программы Go. Для получения дополнительной информации о том, как работать с файлами в Go, прочитайте документацию по файлу ввода-вывода Go.

Использование анонимных структур для декодирования

Целью использования анонимных структур является декодирование только информации, о которой мы заботимся, не засоряя наше приложение типами, которые используются только в одной функции.

jsonBlob := []byte(`
  {
    "_total": 1,
    "_links": {
      "self": "https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=0",
      "next": "https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=25"
    },
    "subscriptions": [
      {
        "created_at": "2011-11-23T02:53:17Z",
        "_id": "abcdef0000000000000000000000000000000000",
        "_links": {
          "self": "https://api.twitch.tv/kraken/channels/foo/subscriptions/bar"
        },
        "user": {
          "display_name": "bar",
          "_id": 123456,
          "name": "bar",
          "staff": false,
          "created_at": "2011-06-16T18:23:11Z",
          "updated_at": "2014-10-23T02:20:51Z",
          "logo": null,
          "_links": {
            "self": "https://api.twitch.tv/kraken/users/bar"
          }
        }
      }
    ]
  }
`)

var js struct {
    Total int `json:"_total"`
    Links struct {
        Next string `json:"next"`
    } `json:"_links"`
    Subs []struct {
        Created string `json:"created_at"`
        User    struct {
            Name string `json:"name"`
            ID   int    `json:"_id"`
        } `json:"user"`
    } `json:"subscriptions"`
}

err := json.Unmarshal(jsonBlob, &js)
if err != nil {
    fmt.Println("error:", err)
}
fmt.Printf("%+v", js)

Вывод: {Total:1 Links:{Next:https://api.twitch.tv/kraken/channels/foo/subscriptions?direction=ASC&limit=25&offset=25} Subs:[{Created:2011-11-23T02:53:17Z User:{Name:bar ID:123456}}]}

Детская площадка

В общем случае см. Также: http://stackoverflow.com/documentation/go/994/json/4111/encoding-decoding-go-structs

Настройка полей структуры JSON

Рассмотрим следующий пример:

type Company struct {
    Name     string
    Location string
}

Скрыть / пропустить определенные поля

Чтобы экспортировать Revenue и Sales , но скрыть их от кодирования / декодирования, используйте json:"-" или переименуйте переменную, чтобы начать с строчной буквы. Обратите внимание, что это предотвращает видимость переменной вне пакета.

type Company struct {
    Name     string `json:"name"`
    Location string `json:"location"`
    Revenue  int    `json:"-"`
    sales    int
}

Игнорировать пустое поле

Чтобы предотвратить включение Location в JSON, когда оно установлено на его нулевое значение, добавьте ,omitempty в тег json .

type Company struct {
    Name     string `json:"name"`
    Location string `json:"location,omitempty"`
}

Пример в игровой площадке

Структуры Marshaling с частными полями

Как хороший разработчик, вы создали следующую структуру с экспортированными и неэкспонированными полями:

type MyStruct struct {
    uuid string    
    Name string
}

Пример на игровой площадке: https://play.golang.org/p/Zk94Il2ANZ

Теперь вы хотите, чтобы Marshal() эта структура была в действительной JSON для хранения в чем-то вроде etcd. Однако, поскольку uuid не экспортируется, json.Marshal() пропускает его. Что делать? Используйте анонимную структуру и интерфейс json.MarshalJSON() ! Вот пример:

type MyStruct struct {
    uuid string    
    Name string
}

func (m MyStruct) MarshalJSON() ([]byte, error {
    j, err := json.Marshal(struct {
        Uuid string
        Name string
    }{
        Uuid: m.uuid,
        Name: m.Name,
    })
    if err != nil {
           return nil, err
    }
    return j, nil
}

Пример на игровой площадке: https://play.golang.org/p/Bv2k9GgbzE

Кодирование / декодирование с использованием структур Go

Предположим, у нас есть следующая struct которая определяет тип City :

type City struct {  
    Name string  
    Temperature int  
}

Мы можем кодировать / декодировать значения City, используя пакет encoding/json .

Прежде всего, нам нужно использовать метаданные Go, чтобы сообщить кодировщику соответствие между строковыми полями и ключами JSON.

type City struct {  
    Name string `json:"name"`  
    Temperature int `json:"temp"`  
    // IMPORTANT: only exported fields will be encoded/decoded  
    // Any field starting with a lower letter will be ignored  
}  

Чтобы этот пример был прост, мы объявим явное соответствие между полями и ключами. Однако вы можете использовать несколько вариантов json: metadata, как описано в документах .

ВАЖНО: Сегментируются / десериализуются только экспортируемые поля (поля с именем). Например, если вы назовете поле t emperature, оно будет проигнорировано, даже если вы установите метаданные json .

кодирование

Чтобы закодировать структуру City , используйте json.Marshal как в базовом примере:

// data to encode  
city := City{Name: "Rome", Temperature: 30}  
 
// encode the data  
bytes, err := json.Marshal(city)  
if err != nil {  
    panic(err)  
}  
 
fmt.Println(string(bytes))  
// {"name":"Rome","temp":30} 

Детская площадка

расшифровка

Чтобы декодировать структуру City , используйте json.Unmarshal как в базовом примере:

// data to decode  
bytes := []byte(`{"name":"Rome","temp":30}`)  
 
// initialize the container for the decoded data  
var city City  
 
// decode the data  
// notice the use of &city to pass the pointer to city  
if err := json.Unmarshal(bytes, &city); err != nil {  
    panic(err)  
}  
 
fmt.Println(city)  
// {Rome 30} 

Детская площадка



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow