Работа с JSON в Golang

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

В этой статье мы рассмотрим различные способы кодирования и декодирования JSON в Golang.

Как отправлять ответы в формате JSON (кодировка)

Кодирование JSON — это процесс преобразования структур данных Go в формат JSON.

Кодирование — это процесс преобразования данных из одного формата в другой. В контексте вычислений и передачи данных кодирование обычно включает преобразование данных в стандартизированный формат, который можно легко хранить, передавать или обрабатывать различными системами или приложениями.

Думайте о кодировании как о сборе чемодана в поездку. Вы берете свою одежду (данные) и упаковываете ее в чемодан (закодированный формат), чтобы ее можно было легко перевезти (передать) и распаковать (расшифровать) в пункте назначения.

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

Некоторые распространенные причины кодирования данных включают в себя:

  • Сжатие данных: уменьшение размера данных для облегчения их хранения или передачи.
  • Безопасность данных: защита данных от несанкционированного доступа или подделки.
  • Совместимость данных: преобразование данных в формат, который может быть прочитан и обработан различными системами или приложениями.
  • Передача данных: Преобразование данных в формат, который можно легко передать по сети или другим каналам связи.

В Голанге мы можем использовать encoding/json пакет для кодирования данных JSON.

Как использовать функцию маршала для кодирования JSON

The Marshal Функция — наиболее часто используемый метод кодирования данных JSON в Golang. Он принимает структуру данных Go в качестве входных данных и возвращает строку в кодировке JSON.

package main

import ( 
    "encoding/json"
    "fmt"
    "net/http"
 )

type Person struct { 
    Name string `json:"name"` 
    Age int `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) { 
    person := Person{  Name: "John",  Age: 30, } 

    // Encoding - One step
    jsonStr, err := json.Marshal(person) 

    if err != nil {  
        http.Error(w, err.Error(), http.StatusInternalServerError)  
        return 
    } 

    w.Write(jsonStr)
}

func main() { 
    http.HandleFunc("/", handler) 
    http.ListenAndServe(":8080", nil)
 }

Объяснение кода:

Импорт:
  • encoding/json: предоставляет функции для кодирования и декодирования JSON.
  • fmt: Для вывода на печать.
Пользовательская структура:
  • Определяет структуру User с полями Name и Age.
  • Структурные теги (например: json:"name") укажите имена ключей JSON.
Основная функция:
  • Создает User пример.
  • Звонки json.Marshal закодировать user структуру в JSON. Это возвращает фрагмент байта и ошибку.
  • Если ошибок нет, он преобразует срез байта в строку и печатает ее.

Как использовать функцию NewEncoder

The NewEncoder Функция используется для кодирования данных JSON для записи, например файла или сетевого подключения.

package main

import ( 
    "encoding/json" 
    "fmt" 
    "net/http"
)

type Person struct { 
    Name string `json:"name"` 
    Age int `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) { 
    person := Person{  Name: "John",  Age: 30 } 

    // Encoding - 2 step . NewEncoder and Encode
    encoder := json.NewEncoder(w) 

    err := encoder.Encode(person) 

    if err != nil {  
        http.Error(w, err.Error(), http.StatusInternalServerError)  

        return 
   }}

func main() { 
   http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)
}

Объяснение кода:

Внутри обработчика:

  • The handler Функция — это обработчик HTTP, который обрабатывает входящие HTTP-запросы.
  • w http.ResponseWriter: Используется для написания ответа.
  • r *http.Request: представляет входящий запрос.
  • А Person экземпляр с именем person был создан и инициализирован значениями Name: "John" и Age: 30.
  • Кодировщик JSON был создан с использованием json.NewEncoder(w), который будет записывать выходные данные JSON в средство записи ответов w.
  • The person Структура была закодирована в JSON и записана в ответ с помощью encoder.Encode(person).
  • Если во время кодирования возникает ошибка, она отправляется обратно клиенту в виде ответа об ошибке HTTP с кодом состояния. 500 Internal Server Error.

Как анализировать запросы JSON (декодирование)

Декодирование JSON — это процесс преобразования данных JSON в структуры данных Go.

Декодирование — это процесс преобразования данных из стандартизированного формата обратно в исходную форму. В вычислениях и передаче данных декодирование включает в себя получение закодированных данных и преобразование их в формат, который можно легко понять и обработать конкретной системой или приложением.

Воспринимайте декодирование как распаковку чемодана после поездки. Вы берете упакованный чемодан (закодированные данные) и распаковываете его, возвращая каждый предмет (данные) на прежнее место, чтобы можно было использовать его снова.

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

Некоторые распространенные причины декодирования данных включают в себя:

  • Извлечение данных: извлечение конкретных данных из более крупного набора закодированных данных.
  • Анализ данных: преобразование закодированных данных в формат, который можно легко проанализировать или обработать.
  • Хранение данных: преобразование закодированных данных в формат, который можно легко сохранить в базе данных или файловой системе.
  • Визуализация данных: преобразование закодированных данных в формат, который можно легко визуализировать или отобразить.

Декодирование — это, по сути, процесс, обратный кодированию, и это важный шаг во многих конвейерах обработки данных.

В Голанге мы можем использовать encoding/json пакет для декодирования данных JSON.

Как использовать функцию демаршалинга для анализа запросов JSON

The Unmarshal Функция — наиболее часто используемый метод декодирования данных JSON в Golang. Он принимает на вход строку в кодировке JSON и возвращает структуру данных Go.

package main

import ( 
    "encoding/json" 
    "fmt" 
    "net/http"
)

type Person struct { 
    Name string `json:"name"` 
    Age int `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) { 
    var person Person err := json.NewDecoder(r.Body).Decode(&person)

    if err != nil {  
        http.Error(w, err.Error(), http.StatusBadRequest)  
        return
    } 

    fmt.Println(person.Name) 
    // Output: John fmt.Println(person.Age) 
    // Output: 30
}

func main() { 
    http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)
}

Объяснение кода:

Внутри обработчика:

  • The handler Функция — это обработчик HTTP, который обрабатывает входящие HTTP-запросы.
  • w http.ResponseWriter: Используется для написания ответа.
  • r *http.Request: представляет входящий запрос.
  • Переменная person типа Person было заявлено.
  • json.NewDecoder(r.Body).Decode(&person): это декодирует тело запроса JSON в person структура.
  • Если во время декодирования возникает ошибка, он отправляет обратно ответ об ошибке HTTP 400 с кодом состояния. 400 Bad Request.
  • Если декодирование прошло успешно, person поля структуры Name и Age печатаются с использованием fmt.Println.

Как использовать функцию NewDecoder для декодирования JSON

The NewDecoder Функция также используется для декодирования данных JSON от устройства чтения, например файла или сетевого подключения.

package main

import ( 
    "encoding/json" 
    "fmt" 
    "net/http"
)

type Person struct { 
    Name string `json:"name"` 
    Age int `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) { 

    decoder := json.NewDecoder(r.Body) 

    var person Person err := decoder.Decode(&person) 

    if err != nil {  
        http.Error(w, err.Error(), http.StatusBadRequest)  
        return 
       } 

    fmt.Println(person.Name) 
    // Output: John fmt.Println(person.Age) 
    // Output: 30
}

func main() { 
    http.HandleFunc("/", handler) 

    http.ListenAndServe(":8080", nil)
 }

Объяснение кода:

Внутри функции-обработчика:

  • The handler Функция — это обработчик HTTP, который обрабатывает входящие HTTP-запросы.
  • w http.ResponseWriter: Используется для написания ответа.
  • r *http.Request: представляет входящий запрос.

Создайте декодер:

  • decoder := json.NewDecoder(r.Body): Создает новый декодер JSON, который считывает текст запроса.

Объявите переменную Person:

  • var person Person: объявляет переменную person типа Person.

Декодируйте JSON в структуру Person:

  • err := decoder.Decode(&person): декодирует JSON из тела запроса в person структура.
  • Если во время декодирования возникает ошибка, он отправляет ответ об ошибке HTTP 400 с кодом состояния. 400 Bad Request и возвращается из функции.

Распечатайте декодированные значения:

  • fmt.Println(person.Name): печать Name поле person структура.
  • fmt.Println(person.Age): печать Age поле person структура.

Пользовательская маршалинг и демаршалинг JSON

В некоторых случаях поведение кодирования и декодирования JSON по умолчанию, предоставляемое json.Marshal и json.Unmarshal может быть недостаточно. Например, вам может потребоваться настроить представление определенных полей в JSON. Именно здесь json.Marshaler и json.Unmarshaler интерфейсы пригодятся.

Как использовать маршалер JSON

The json.Marshaler Интерфейс позволяет вам настроить кодировку JSON типа, реализовав MarshalJSON метод. Этот метод возвращает фрагмент байта в формате JSON и ошибку.

func (p Person) MarshalJSON() ([]byte, error) {
    type Alias Person
    return json.Marshal(&struct {
        Alias
        Age string `json:"age"`
    }{
        Alias: (Alias)(p),
        Age:   strconv.Itoa(p.Age) + " years",
    })
}

В этом примере Age поле преобразуется в строку с суффиксом «годы» при кодировании в JSON.

Как использовать JSON Unmarshaler

The json.Unmarshaler Интерфейс позволяет вам настроить декодирование типа JSON, реализовав UnmarshalJSON метод. Этот метод принимает фрагмент байта в формате JSON и возвращает ошибку.

func (p *Person) UnmarshalJSON(data []byte) error {
    type Alias Person
    aux := &struct {
        Alias
        Age string `json:"age"`
    }{Alias: (Alias)(*p)}

    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }

    ageStr := strings.TrimSuffix(aux.Age, " years")
    age, err := strconv.Atoi(ageStr)
    if err != nil {
        return err
    }

    p.Age = age
    p.Name = aux.Name
    return nil
}

В этом примере Age Поле преобразуется из строки с суффиксом «лет» в целое число при декодировании из JSON.

Компромиссы

Из различных описанных выше методов кодирования и декодирования JSON. Вот компромиссы для наиболее часто используемых методов:

json.Marshal и json.Unmarshal:

Плюсы:

  • Простота использования : простота кодирования (маршал) и декодирования (демаршал) JSON.
  • Гибкость : может использоваться с различными типами, включая структуры, карты, фрагменты и многое другое.
  • Настройка : Структурные теги ( json:"name") позволяют настраивать ключи JSON и другие параметры.

Минусы:

  • Производительность : возможно, это не самый быстрый метод для очень больших или сложных структур JSON.
  • Обработка ошибок . Сообщения об ошибках иногда могут быть менее информативными для глубоко вложенных или сложных структур данных.

json.NewEncoder и json.NewDecoder:

Плюсы:

  • Потоковый : подходит для кодирования/декодирования JSON в потоковом режиме, который может обрабатывать большие наборы данных, не потребляя много памяти.
  • Гибкость : Может работать напрямую с io.Reader и io.Writer интерфейсы, что делает их полезными для сетевых операций и больших файлов.

Минусы:

  • Сложность : немного сложнее в использовании по сравнению с json.Marshal и json.Unmarshal.
  • Обработка ошибок : аналогично json.Marshal и json.Unmarshal, сообщения об ошибках могут быть менее понятными для сложных структур.

Пользовательские интерфейсы маршалера и демаршалера (json.Marshaler и json.Unmarshaler):

Плюсы:

  • Настройка : Полный контроль над тем, как кодируются/декодируются типы. Полезно для обработки сложных типов или пользовательских структур JSON.
  • Гибкость : позволяет реализовать собственную логику во время маршалинга/демаршалинга.

Минусы:

  • Сложность : более сложна в реализации и использовании, поскольку требует написания собственных методов.
  • Обслуживание : увеличивает нагрузку на обслуживание, поскольку пользовательскую логику необходимо синхронизировать с любыми изменениями в структуре или формате данных.

Варианты использования и рекомендации

  • Простые структуры данных : использование json.Marshal и json.Unmarshal для прямого кодирования/декодирования простых структур данных.
  • Большие потоки данных : используйте json.NewEncoder и json.NewDecoder для работы с большими потоками данных или при взаимодействии с файлами или сетевыми операциями.
  • Пользовательские требования : Реализация json.Marshaler и json.Unmarshaler интерфейсы, когда вам нужно настраиваемое поведение для определенных типов.
  • Быстрые операции . Используйте анонимные структуры для быстрых одноразовых операций, когда определение полного типа структуры не требуется.

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

Заключение

В заключение, освоение кодирования и декодирования JSON имеет решающее значение для разработки веб-приложений на Golang.

Понимая различные методы, доступные в encoding/json пакета, вы можете выбрать наиболее подходящий подход, исходя из ваших конкретных требований.

The Marshal и Unmarshal функции обеспечивают простоту и гибкость для общего использования, в то время как NewEncoder и NewDecoder обеспечить эффективные возможности потоковой передачи больших наборов данных.

Для сценариев, требующих настраиваемых представлений JSON, реализация json.Marshaler и json.Unmarshaler Интерфейсы дают вам детальный контроль над процессами кодирования и декодирования.

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