Spec-Zone.ru › Go

Пакет json

  • import "encoding/json"
  • Обзор
  • Указатель
  • Примеры
  • Подкаталоги

Обзор

Пакет json реализует кодирование и декодирование JSON в соответствии с RFC 7159. Сопоставление между значениями JSON и Go описано в документации функций Marshal и Unmarshal.

Введение в этот пакет см. в статье JSON и Go.

Вопросы безопасности

См. раздел «Вопросы безопасности» в encoding/json/v2.

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

Переход на v2

Теперь этот пакет (то есть encoding/json) официально называется пакетом v1, поскольку появился пакет v2 — encoding/json/v2. Всё поведение пакета v1 реализовано средствами пакета v2 с указанием соответствующего набора параметров, сохраняющего историческое поведение v1.

Функция jsonv2.Marshal — новый эквивалент Marshal из v1. Функция jsonv2.Unmarshal — новый эквивалент Unmarshal из v1. Функции v2 имеют те же сигнатуры вызова, что и соответствующие функции v1, за исключением того, что они принимают вариативные аргументы Options, с помощью которых можно изменить поведение маршалинга или анмаршалинга. В целом v1 и v2 ведут себя сходным образом, но есть несколько существенных различий.

Ниже перечислены различия между v1 и v2:

  • В v1 члены объекта JSON анмаршалятся в структуру Go с использованием нечувствительного к регистру сопоставления с именами полей JSON. В отличие от этого, v2 сопоставляет поля с точным учетом регистра. Это различие в поведении контролируют параметры jsonv2.MatchCaseInsensitiveNames и MatchCaseSensitiveDelimiter. Чтобы явно указать для поля структуры Go конкретную схему сопоставления имен, можно задать параметр поля `case:ignore` или `case:strict`. Параметры, заданные для полей, имеют приоритет над параметрами, заданными вызывающей стороной.

  • В v1 при маршалинге структуры Go поле с пометкой `omitempty` пропускается, если его значение является «пустым» значением Go, которым считается false, 0, nil-указатель, nil-значение интерфейса, а также любой пустой массив, срез, map или строка. В отличие от этого, в v2 значение `omitempty` переопределено: поле пропускается, если оно кодируется как «пустое» значение JSON, которым считается JSON null или пустая строка, объект либо массив JSON. Это различие в поведении контролирует параметр OmitEmptyWithLegacySemantics. Обратите внимание, что для массива, среза, map или строки Go `omitempty` работает одинаково в v1 и v2 (при условии, что пользовательский метод MarshalJSON не переопределяет представление по умолчанию). Существующее использование `omitempty` для значения Go типа bool, числа, указателя или интерфейса следует заменить на `omitzero` (который одинаково поддерживается в v1 и v2).

  • В v1 поле структуры Go с пометкой `string` можно использовать, чтобы заключить строку, bool, число или указатель на них в строку JSON. В отличие от этого, v2 ограничивает параметр `string`: он заключает в строку только значение, которое обычно представляется как число JSON, но при этом расширяет его поддержку на любой тип Go, который обычно представляется как число JSON. Это различие в поведении контролирует параметр StringifyWithLegacySemantics.

  • В v1 nil-срез Go или nil-map маршалится как JSON null. В отличие от этого, v2 маршалит nil-срез Go как пустой массив JSON, а nil-map Go — как пустой объект JSON. Это различие в поведении контролируют параметры jsonv2.FormatNilSliceAsNull и jsonv2.FormatNilMapAsNull.

  • В v1 массив Go можно анмаршалить из массива JSON любой длины. В отличие от этого, в v2 массив Go должен анмаршалиться из массива JSON той же длины; в противном случае возникает ошибка. Это различие в поведении контролирует параметр UnmarshalArrayFromAnyLength.

  • В v1 байтовый массив Go представляется как массив чисел JSON. В отличие от этого, в v2 байтовый массив Go представляется как строка JSON в кодировке Base64. Это различие в поведении контролирует параметр FormatByteArrayAsArray.

  • В v1 методы MarshalJSON, объявленные с указателем-получателем, вызываются только в том случае, если значение Go адресуемо. В отличие от этого, в v2 метод MarshalJSON всегда можно вызвать независимо от адресуемости. Это различие в поведении контролирует параметр CallMethodsWithLegacySemantics.

  • В v1 методы MarshalJSON и UnmarshalJSON никогда не вызываются для ключей map Go. В отличие от этого, в v2 методы MarshalJSON и UnmarshalJSON могут вызываться для ключей map Go. Это различие в поведении контролирует параметр CallMethodsWithLegacySemantics.

  • В v1 map Go маршалится в детерминированном порядке. В отличие от этого, в v2 map Go маршалится в недетерминированном порядке. Это различие в поведении контролирует параметр jsonv2.Deterministic.

  • В v1 при кодировании строк JSON экранируются символы, специфичные для HTML или JavaScript. В отличие от этого, в v2 строки JSON используют минимальное кодирование и экранируются только тогда, когда этого требует грамматика JSON. Это различие в поведении контролируют параметры jsontext.EscapeForHTML и jsontext.EscapeForJS.

  • В v1 байты некорректной UTF-8 внутри строки незаметно заменяются символом замены Unicode. В отличие от этого, в v2 наличие некорректной UTF-8 приводит к ошибке. Это различие в поведении контролирует параметр jsontext.AllowInvalidUTF8.

  • В v1 объект JSON может содержать повторяющиеся имена. В отличие от этого, наличие повторяющихся имен в объекте JSON в v2 приводит к ошибке. Это различие в поведении контролирует параметр jsontext.AllowDuplicateNames.

  • В v1 при анмаршалинге JSON null в непустое значение Go это значение непоследовательно либо обнуляется, либо не изменяется. В отличие от этого, в v2 при анмаршалинге JSON null базовое значение Go всегда и неизменно обнуляется. Это различие в поведении контролирует параметр MergeWithLegacySemantics.

  • В v1 при анмаршалинге значения JSON в ненулевое значение Go результат объединяется с исходным значением Go для элементов массива и среза, полей структуры (но не значений map), значений указателей и значений интерфейсов (только если это ненулевой указатель). В отличие от этого, в v2 анмаршалинг объединяет результат со значением Go для полей структуры, значений map, значений указателей и значений интерфейсов. В общем случае семантика v2 объединяет значения при анмаршалинге объекта JSON, а в остальных случаях заменяет значение. Это различие в поведении контролирует параметр MergeWithLegacySemantics.

  • В v1 значение time.Duration представляется как число JSON, содержащее десятичное количество наносекунд. В отличие от этого, в v2 для time.Duration нет представления по умолчанию, и возникает ошибка времени выполнения. Это различие в поведении контролирует параметр FormatDurationAsNano.

  • В v1 ошибки времени выполнения никогда не сообщаются для типов структур Go, содержащих какую-либо структурную ошибку (например, некорректный параметр тега). В отличие от этого, v2 сообщает об ошибке времени выполнения для типов Go, недопустимых с точки зрения сериализации JSON. Например, структуру Go, содержащую только непубличные поля, сериализовать нельзя. Это различие в поведении контролирует параметр ReportErrorsWithLegacySemantics.

Как упоминалось выше, v1 целиком реализован средствами v2, при этом параметры неявно задаются для включения обратной совместимости. Например, Marshal напрямую вызывает jsonv2.Marshal с параметром DefaultOptionsV1. Аналогично, Unmarshal напрямую вызывает jsonv2.Unmarshal с параметром DefaultOptionsV1. Параметр DefaultOptionsV1 представляет набор всех параметров, задающих поведение v1 по умолчанию.

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

Наличие DefaultOptionsV1 и jsonv2.DefaultOptionsV2, при котором более поздние параметры имеют приоритет над более ранними, позволяет постепенно перейти с v1 на v2. Например:

  • jsonv1.Marshal(v) использует семантику v1 по умолчанию.

  • jsonv2.Marshal(v, jsonv1.DefaultOptionsV1()) семантически эквивалентен jsonv1.Marshal и, следовательно, использует семантику v1 по умолчанию.

  • jsonv2.Marshal(v, jsonv1.DefaultOptionsV1(), jsontext.AllowDuplicateNames(false)) в основном использует семантику v1, но включает одно конкретное поведение, характерное для v2.

  • jsonv2.Marshal(v, jsonv1.CallMethodsWithLegacySemantics(true)) в основном использует семантику v2, но включает одно конкретное поведение, характерное для v1.

  • jsonv2.Marshal(v, ..., jsonv2.DefaultOptionsV2()) семантически эквивалентен jsonv2.Marshal, поскольку jsonv2.DefaultOptionsV2 переопределяет все параметры, заданные ранее, и поэтому использует семантику v2 по умолчанию.

  • jsonv2.Marshal(v) использует семантику v2 по умолчанию.

Во всех новых местах использования «json» в Go следует использовать пакет v2, но пакет v1 останется поддерживаемым и впредь.

Дополнительные сведения о способах перехода см. в руководстве по переходу на encoding/json/v2.

Пример (CustomMarshalJSON)

Код:

package json_test

import (
    "fmt"
    "log"
    "strings"

    "encoding/json"
)

type Animal int

const (
    Unknown Animal = iota
    Gopher
    Zebra
)

func (a *Animal) UnmarshalJSON(b []byte) error {
    var s string
    if err := json.Unmarshal(b, &s); err != nil {
        return err
    }
    switch strings.ToLower(s) {
    default:
        *a = Unknown
    case "gopher":
        *a = Gopher
    case "zebra":
        *a = Zebra
    }

    return nil
}

func (a Animal) MarshalJSON() ([]byte, error) {
    var s string
    switch a {
    default:
        s = "unknown"
    case Gopher:
        s = "gopher"
    case Zebra:
        s = "zebra"
    }

    return json.Marshal(s)
}

func Example_customMarshalJSON() {
    blob := `["gopher","armadillo","zebra","unknown","gopher","bee","gopher","zebra"]`
    var zoo []Animal
    if err := json.Unmarshal([]byte(blob), &zoo); err != nil {
        log.Fatal(err)
    }

    census := make(map[Animal]int)
    for _, animal := range zoo {
        census[animal] += 1
    }

    fmt.Printf("Zoo Census:\n* Gophers: %d\n* Zebras:  %d\n* Unknown: %d\n",
        census[Gopher], census[Zebra], census[Unknown])

    // Output:
    // Zoo Census:
    // * Gophers: 3
    // * Zebras:  2
    // * Unknown: 3
}

Пример (TextMarshalJSON)

Код:

package json_test

import (
    "fmt"
    "log"
    "strings"

    "encoding/json"
)

type Size int

const (
    Unrecognized Size = iota
    Small
    Large
)

func (s *Size) UnmarshalText(text []byte) error {
    switch strings.ToLower(string(text)) {
    default:
        *s = Unrecognized
    case "small":
        *s = Small
    case "large":
        *s = Large
    }
    return nil
}

func (s Size) MarshalText() ([]byte, error) {
    var name string
    switch s {
    default:
        name = "unrecognized"
    case Small:
        name = "small"
    case Large:
        name = "large"
    }
    return []byte(name), nil
}

func Example_textMarshalJSON() {
    blob := `["small","regular","large","unrecognized","small","normal","small","large"]`
    var inventory []Size
    if err := json.Unmarshal([]byte(blob), &inventory); err != nil {
        log.Fatal(err)
    }

    counts := make(map[Size]int)
    for _, size := range inventory {
        counts[size] += 1
    }

    fmt.Printf("Inventory Counts:\n* Small:        %d\n* Large:        %d\n* Unrecognized: %d\n",
        counts[Small], counts[Large], counts[Unrecognized])

    // Output:
    // Inventory Counts:
    // * Small:        3
    // * Large:        2
    // * Unrecognized: 3
}

Указатель

  • func Compact(dst *bytes.Buffer, src []byte) error
  • func HTMLEscape(dst *bytes.Buffer, src []byte)
  • func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
  • func Marshal(v any) ([]byte, error)
  • func MarshalIndent(v any, prefix, indent string) ([]byte, error)
  • func Unmarshal(data []byte, v any) error
  • func Valid(data []byte) bool
  • type Decoder
  • func NewDecoder(r io.Reader) *Decoder
  • func (dec *Decoder) Buffered() io.Reader
  • func (dec *Decoder) Decode(v any) error
  • func (dec *Decoder) DisallowUnknownFields()
  • func (dec *Decoder) InputOffset() int64
  • func (dec *Decoder) More() bool
  • func (dec *Decoder) Token() (Token, error)
  • func (dec *Decoder) UseNumber()
  • type Delim
  • func (d Delim) String() string
  • type Encoder
  • func NewEncoder(w io.Writer) *Encoder
  • func (enc *Encoder) Encode(v any) error
  • func (enc *Encoder) SetEscapeHTML(on bool)
  • func (enc *Encoder) SetIndent(prefix, indent string)
  • type InvalidUTF8Error
  • func (e *InvalidUTF8Error) Error() string
  • type InvalidUnmarshalError
  • func (e *InvalidUnmarshalError) Error() string
  • type Marshaler
  • type MarshalerError
  • func (e *MarshalerError) Error() string
  • func (e *MarshalerError) Unwrap() error
  • type Number
  • func (n Number) Float64() (float64, error)
  • func (n Number) Int64() (int64, error)
  • func (n Number) MarshalJSONTo(enc *jsontext.Encoder) error
  • func (n Number) String() string
  • func (n *Number) UnmarshalJSONFrom(dec *jsontext.Decoder) error
  • type Options
  • func CallMethodsWithLegacySemantics(v bool) Options
  • func DefaultOptionsV1() Options
  • func FormatByteArrayAsArray(v bool) Options
  • func FormatBytesWithLegacySemantics(v bool) Options
  • func FormatDurationAsNano(v bool) Options
  • func MatchCaseSensitiveDelimiter(v bool) Options
  • func MergeWithLegacySemantics(v bool) Options
  • func OmitEmptyWithLegacySemantics(v bool) Options
  • func ParseBytesWithLooseRFC4648(v bool) Options
  • func ParseTimeWithLooseRFC3339(v bool) Options
  • func ReportErrorsWithLegacySemantics(v bool) Options
  • func StringifyWithLegacySemantics(v bool) Options
  • func UnmarshalArrayFromAnyLength(v bool) Options
  • type RawMessage
  • type SyntaxError
  • func (e *SyntaxError) Error() string
  • type Token
  • type UnmarshalFieldError
  • func (e *UnmarshalFieldError) Error() string
  • type UnmarshalTypeError
  • func (e *UnmarshalTypeError) Error() string
  • func (e *UnmarshalTypeError) Unwrap() error
  • type Unmarshaler
  • type UnsupportedTypeError
  • func (e *UnsupportedTypeError) Error() string
  • type UnsupportedValueError
  • func (e *UnsupportedValueError) Error() string

Примеры

Decoder
Decoder.Decode (поток)
Decoder.Token
HTMLEscape
Indent
Marshal
MarshalIndent
RawMessage (Marshal)
RawMessage (Unmarshal)
Unmarshal
Valid
Package (CustomMarshalJSON)
Package (TextMarshalJSON)

Файлы пакета

v2_decode.go v2_encode.go v2_indent.go v2_inject.go v2_options.go v2_scanner.go v2_stream.go

func Compact

func Compact(dst *bytes.Buffer, src []byte) error

Compact добавляет к dst данные src в кодировке JSON, удаляя незначащие пробелы.

func HTMLEscape

func HTMLEscape(dst *bytes.Buffer, src []byte)

HTMLEscape добавляет к dst данные src в кодировке JSON, заменяя символы <, >, &, U+2028 и U+2029 внутри строковых литералов на \u003c, \u003e, \u0026, \u2028, \u2029, чтобы JSON можно было безопасно встраивать в теги <script> HTML. По историческим причинам веб-браузеры не соблюдают стандартное экранирование HTML внутри тегов <script>, поэтому необходимо использовать альтернативное кодирование JSON.

Пример

Код:

var out bytes.Buffer
json.HTMLEscape(&out, []byte(`{"Name":"<b>HTML content</b>"}`))
out.WriteTo(os.Stdout)

Вывод:

{"Name":"\u003cb\u003eHTML content\u003c/b\u003e"}

func Indent

func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error

Indent добавляет к dst данные src в кодировке JSON с отступами. Каждый элемент объекта или массива JSON начинается с новой строки с отступом: сначала prefix, за которым следует одна или несколько копий indent в соответствии с уровнем вложенности. Добавляемые к dst данные не начинаются с prefix или отступа, что упрощает их встраивание в другие форматированные данные JSON. Начальные пробелы (пробел, табуляция, возврат каретки, новая строка) в начале src удаляются, но конечные пробелы в конце src сохраняются и копируются в dst. Например, если src не заканчивается пробелами, то и dst не будет; если src заканчивается символом новой строки, dst тоже будет им заканчиваться.

Пример

Код:

type Road struct {
    Name   string
    Number int
}
roads := []Road{
    {"Diamond Fork", 29},
    {"Sheep Creek", 51},
}

b, err := json.Marshal(roads)
if err != nil {
    log.Fatal(err)
}

var out bytes.Buffer
json.Indent(&out, b, "=", "\t")
out.WriteTo(os.Stdout)

Вывод:

[
=	{
=		"Name": "Diamond Fork",
=		"Number": 29
=	},
=	{
=		"Name": "Sheep Creek",
=		"Number": 51
=	}
=]

func Marshal

func Marshal(v any) ([]byte, error)

Marshal возвращает кодированное представление v в формате JSON.

Marshal рекурсивно обходит значение v.

Входное значение кодируется в формате JSON по следующим правилам:

  • Если тип значения реализует jsonv2.MarshalerTo, для кодирования значения вызывается метод MarshalJSONTo. Если метод возвращает errors.ErrUnsupported, входные данные кодируются согласно последующим правилам.

  • Если тип значения реализует Marshaler, для кодирования значения вызывается метод MarshalJSON.

  • Если тип значения реализует encoding.TextAppender, для кодирования значения вызывается метод AppendText, а затем его результат кодируется как строка JSON.

  • Если тип значения реализует encoding.TextMarshaler, для кодирования значения вызывается метод MarshalText, а затем его результат кодируется как строка JSON.

В противном случае Marshal использует следующие кодировки по умолчанию, зависящие от типа:

Логические значения кодируются как логические значения JSON.

Значения с плавающей точкой, целые числа и значения типа Number кодируются как числа JSON. Для значений NaN и +/-Inf возвращается ошибка UnsupportedValueError.

Строковые значения кодируются как строки JSON, преобразуемые в корректную UTF-8: некорректные байты заменяются символом замены Unicode. Чтобы JSON можно было безопасно встраивать в теги <script> HTML, строка кодируется с помощью HTMLEscape, которая экранирует символы "<", ">", "&", U+2028 и U+2029 как "\u003c", "\u003e", "\u0026", "\u2028" и "\u2029". Это преобразование можно отключить для Encoder, вызвав Encoder.SetEscapeHTML(false).

Значения массивов и срезов кодируются как массивы JSON, за исключением []byte, который кодируется как строка в кодировке base64, и nil-среза, который кодируется как значение JSON null.

Значения структур кодируются как объекты JSON. Каждое экспортированное поле структуры становится членом объекта, а ключом объекта служит имя поля, если поле не пропущено по одной из причин, указанных ниже.

Кодирование каждого поля структуры можно настроить с помощью строки формата, указанной под ключом "json" в теге поля структуры. Строка формата задаёт имя поля, за которым может следовать разделённый запятыми список параметров. Имя может быть пустым, чтобы задать параметры, не переопределяя имя поля по умолчанию.

Параметр "omitempty" указывает, что поле следует пропустить при кодировании, если оно имеет пустое значение: false, 0, nil-указатель, nil-значение интерфейса или массив, срез, map либо строка нулевой длины.

В особом случае, если тег поля равен "-", поле всегда пропускается. Имена JSON, содержащие запятые или кавычки, а также имена, совпадающие с "" или "-", можно задавать строковым литералом в одинарных кавычках. Его синтаксис совпадает с синтаксисом строкового литерала Go в двойных кавычках, но в качестве разделителей используются одинарные кавычки.

Примеры тегов полей структуры и их значения:

// Field appears in JSON as key "myName".
Field int `json:"myName"`

// Field appears in JSON as key "myName" and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `json:"myName,omitempty"`

// Field appears in JSON as key "Field" (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `json:",omitempty"`

// Field is ignored by this package.
Field int `json:"-"`

// Field appears in JSON as key "-".
Field int `json:"'-'"`

Параметр "omitzero" указывает, что поле следует пропустить при кодировании, если оно имеет нулевое значение, определяемое по следующим правилам:

1) Если у типа поля есть метод "IsZero() bool", он используется для определения того, является ли значение нулевым.

2) В противном случае значение считается нулевым, если оно является нулевым значением своего типа.

Если заданы оба параметра — "omitempty" и "omitzero", поле будет пропущено, если значение пустое или нулевое (либо и то и другое).

Параметр "string" указывает, что поле хранится в виде JSON внутри строки, закодированной в JSON. Он применим только к полям строкового типа, типа с плавающей точкой, целочисленного или логического типа. Этот дополнительный уровень кодирования иногда используется при взаимодействии с программами на JavaScript:

Int64String int64 `json:",string"`

Имя ключа будет использоваться, если оно представляет собой непустую строку, состоящую только из букв Unicode, цифр и знаков пунктуации ASCII, кроме кавычек, обратной косой черты и запятой.

Вложенные поля структур обычно маршалятся так, словно их внутренние экспортированные поля являются полями внешней структуры, с учетом обычных правил видимости Go и изменений, описанных в следующем абзаце. Анонимное поле структуры с именем, заданным в его теге JSON, считается имеющим это имя, а не анонимным. Анонимное поле структуры интерфейсного типа считается имеющим имя этого типа, а не анонимным.

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

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

2) Если после применения первого правила осталось ровно одно поле (с тегом или без), выбирается оно.

3) В противном случае остается несколько полей, и все они игнорируются; ошибка не возникает.

Поддержка анонимных полей структур появилась в Go 1.1. До Go 1.1 анонимные поля структур игнорировались. Чтобы игнорировать анонимное поле структуры и в текущих, и в более ранних версиях, укажите для него тег JSON "-".

Значения map кодируются как объекты JSON. Тип ключа map должен быть строковым типом, целочисленным типом или реализовывать encoding.TextMarshaler. Ключи map сортируются и используются в качестве ключей объектов JSON по следующим правилам, с учетом преобразования в UTF-8, описанного выше для строковых значений:

  • ключи любых строковых типов используются непосредственно
  • ключи, реализующие encoding.TextMarshaler, маршалятся
  • целочисленные ключи преобразуются в строки

Значения-указатели кодируются как значения, на которые они указывают. nil-указатель кодируется как значение JSON null.

Значения интерфейсов кодируются как содержащиеся в них значения. nil-значение интерфейса кодируется как значение JSON null.

Значения каналов, комплексных чисел и функций нельзя кодировать в JSON. Попытка закодировать такое значение приводит к тому, что Marshal возвращает ошибку UnsupportedTypeError.

JSON не может представлять циклические структуры данных, и Marshal их не обрабатывает. Передача циклических структур в Marshal приводит к ошибке.

Пример

Код:

type ColorGroup struct {
    ID     int
    Name   string
    Colors []string
}
group := ColorGroup{
    ID:     1,
    Name:   "Reds",
    Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
    fmt.Println("error:", err)
}
os.Stdout.Write(b)

Вывод:

{"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}

func MarshalIndent

func MarshalIndent(v any, prefix, indent string) ([]byte, error)

MarshalIndent работает как Marshal, но форматирует вывод с помощью Indent. Каждый элемент JSON в выводе начинается с новой строки с отступом: сначала prefix, за которым следует одна или несколько копий indent в соответствии с уровнем вложенности.

Пример

Код:

data := map[string]int{
    "a": 1,
    "b": 2,
}

b, err := json.MarshalIndent(data, "<prefix>", "<indent>")
if err != nil {
    log.Fatal(err)
}

fmt.Println(string(b))

Вывод:

{
<prefix><indent>"a": 1,
<prefix><indent>"b": 2
<prefix>}

func Unmarshal

func Unmarshal(data []byte, v any) error

Unmarshal разбирает данные в кодировке JSON и сохраняет результат в значении, на которое указывает v. Если v равен nil или не является указателем, Unmarshal возвращает ошибку InvalidUnmarshalError.

Unmarshal использует обратные кодировки по отношению к тем, которые использует Marshal, выделяя при необходимости память для map, срезов и указателей, а также применяет следующие дополнительные правила:

При анмаршалинге JSON в указатель Unmarshal сначала обрабатывает случай, когда JSON представляет собой литерал JSON null. В этом случае Unmarshal присваивает указателю nil. В противном случае Unmarshal анмаршалит JSON в значение, на которое указывает указатель. Если указатель равен nil, Unmarshal выделяет новое значение, на которое он будет указывать.

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

  • Если тип значения реализует jsonv2.UnmarshalerFrom, для декодирования значения JSON вызывается метод UnmarshalJSONFrom. Если метод возвращает errors.ErrUnsupported, входные данные декодируются согласно последующим правилам.

  • Если тип значения реализует Unmarshaler, для декодирования значения JSON вызывается метод UnmarshalJSON, в том числе когда входное значение — JSON null.

  • Если значение реализует encoding.TextUnmarshaler, а входное значение представляет собой строку JSON, метод UnmarshalText вызывается с неэкранированным содержимым строки.

В противном случае Unmarshal использует следующие декодирования по умолчанию, зависящие от типа:

При анмаршалинге JSON в структуру Unmarshal сопоставляет входящие ключи объекта с ключами, которые использует Marshal (именами полей структуры или их тегами), отдавая предпочтение точному совпадению, но также принимая совпадения без учета регистра. По умолчанию ключи объекта, которым не соответствует поле структуры, игнорируются (альтернативный вариант см. в Decoder.DisallowUnknownFields).

При анмаршалинге JSON в значение интерфейса Unmarshal сохраняет в этом значении один из следующих типов:

  • bool для логических значений JSON
  • float64 для чисел JSON
  • string для строк JSON
  • []any для массивов JSON
  • map[string]any для объектов JSON
  • nil для JSON null

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

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

При анмаршалинге объекта JSON в map Unmarshal сначала выбирает map для использования. Если map равен nil, Unmarshal выделяет новую map. В противном случае Unmarshal повторно использует существующую map, сохраняя имеющиеся записи. Затем Unmarshal помещает в map пары ключ-значение из объекта JSON. Тип ключа map должен быть строковым типом, целым числом или реализовывать encoding.TextUnmarshaler.

Если в данных JSON обнаружена синтаксическая ошибка, Unmarshal возвращает SyntaxError.

Если значение JSON не подходит для заданного целевого типа или число JSON выходит за пределы целевого типа, Unmarshal пропускает это поле и по возможности завершает анмаршалинг. Если не возникает более серьезных ошибок, Unmarshal возвращает UnmarshalTypeError с описанием самой ранней такой ошибки. В любом случае не гарантируется, что все оставшиеся после проблемного поля поля будут анмаршалены в целевой объект.

Значение JSON null анмаршалится в интерфейс, map, указатель или срез путем присваивания соответствующему значению Go значения nil. Поскольку в JSON null часто означает «отсутствует», анмаршалинг JSON null в любой другой тип Go не влияет на значение и не приводит к ошибке.

При анмаршалинге строк в кавычках некорректные UTF-8 и пары суррогатов UTF-16 не считаются ошибкой. Вместо этого они заменяются символом замены Unicode U+FFFD.

Пример

Код:

var jsonBlob = []byte(`[
    {"Name": "Platypus", "Order": "Monotremata"},
    {"Name": "Quoll",    "Order": "Dasyuromorphia"}
]`)
type Animal struct {
    Name  string
    Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
    fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)

Вывод:

[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]

func Valid 1.9

func Valid(data []byte) bool

Valid сообщает, являются ли данные допустимым представлением JSON.

Пример

Код:

goodJSON := `{"example": 1}`
badJSON := `{"example":2:]}}`

fmt.Println(json.Valid([]byte(goodJSON)), json.Valid([]byte(badJSON)))

Вывод:

true false

type Decoder

Decoder считывает и декодирует значения JSON из входного потока.

type Decoder struct {
    // contains filtered or unexported fields
}

Пример

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

Код:

const jsonStream = `
    {"Name": "Ed", "Text": "Knock knock."}
    {"Name": "Sam", "Text": "Who's there?"}
    {"Name": "Ed", "Text": "Go fmt."}
    {"Name": "Sam", "Text": "Go fmt who?"}
    {"Name": "Ed", "Text": "Go fmt yourself!"}
`
type Message struct {
    Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
    var m Message
    if err := dec.Decode(&m); err == io.EOF {
        break
    } else if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s: %s\n", m.Name, m.Text)
}

Вывод:

Ed: Knock knock.
Sam: Who's there?
Ed: Go fmt.
Sam: Go fmt who?
Ed: Go fmt yourself!

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder возвращает новый декодер, считывающий данные из r.

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

func (*Decoder) Buffered 1.1

func (dec *Decoder) Buffered() io.Reader

Buffered возвращает reader данных, оставшихся в непрочитанном буфере, который может содержать ноль или более байтов. Это данные, уже считанные из входного io.Reader, но еще не прочитанные вызовом Decoder.Decode или Decoder.Token. Они могут содержать байты, не образующие допустимый JSON, поскольку эти данные еще не проверялись на соответствие грамматике JSON. Точный объем буферизованных данных является деталью реализации Decoder и может меняться со временем.

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

Reader действителен до следующего вызова Decoder.Decode или Decoder.Token.

func (*Decoder) Decode

func (dec *Decoder) Decode(v any) error

Decode считывает следующее значение, закодированное в формате JSON, из входных данных и сохраняет его в значении, на которое указывает v.

Подробнее о преобразовании JSON в значение Go см. в документации Unmarshal.

Пример (поток)

В этом примере Decoder используется для декодирования потокового массива объектов JSON.

Код:

const jsonStream = `
    [
        {"Name": "Ed", "Text": "Knock knock."},
        {"Name": "Sam", "Text": "Who's there?"},
        {"Name": "Ed", "Text": "Go fmt."},
        {"Name": "Sam", "Text": "Go fmt who?"},
        {"Name": "Ed", "Text": "Go fmt yourself!"}
    ]
`
type Message struct {
    Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))

// read open bracket
t, err := dec.Token()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)

// while the array contains values
for dec.More() {
    var m Message
    // decode an array value (Message)
    err := dec.Decode(&m)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v: %v\n", m.Name, m.Text)
}

// read closing bracket
t, err = dec.Token()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)

Вывод:

json.Delim: [
Ed: Knock knock.
Sam: Who's there?
Ed: Go fmt.
Sam: Go fmt who?
Ed: Go fmt yourself!
json.Delim: ]

func (*Decoder) DisallowUnknownFields 1.10

func (dec *Decoder) DisallowUnknownFields()

DisallowUnknownFields заставляет Decoder возвращать ошибку, если целевое значение является структурой, а входные данные содержат ключи объектов, не соответствующие ни одному экспортируемому полю целевой структуры, кроме игнорируемых полей.

func (*Decoder) InputOffset 1.14

func (dec *Decoder) InputOffset() int64

InputOffset возвращает смещение в байтах во входном потоке для текущей позиции декодера. Смещение указывает расположение конца последнего возвращенного токена и начала следующего токена.

func (*Decoder) More 1.5

func (dec *Decoder) More() bool

More сообщает, есть ли еще один элемент в текущем разбираемом массиве или объекте.

func (*Decoder) Token 1.5

func (dec *Decoder) Token() (Token, error)

Token возвращает следующий токен JSON во входном потоке. В конце входного потока Token возвращает nil, io.EOF.

Token гарантирует, что возвращаемые им разделители [ ] { } правильно вложены и сопоставлены: если Token обнаруживает во входных данных неожиданный разделитель, он возвращает ошибку.

Входной поток состоит из базовых значений JSON — bool, string, number и null — а также разделителей [ ] { } типа Delim, обозначающих начало и конец массивов и объектов. Запятые и двоеточия опускаются.

Пример

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

Код:

const jsonStream = `
    {"Message": "Hello", "Array": [1, 2, 3], "Null": null, "Number": 1.234}
`
dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
    t, err := dec.Token()
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%T: %v", t, t)
    if dec.More() {
        fmt.Printf(" (more)")
    }
    fmt.Printf("\n")
}

Вывод:

json.Delim: { (more)
string: Message (more)
string: Hello (more)
string: Array (more)
json.Delim: [ (more)
float64: 1 (more)
float64: 2 (more)
float64: 3
json.Delim: ] (more)
string: Null (more)
<nil>: <nil> (more)
string: Number (more)
float64: 1.234
json.Delim: }

func (*Decoder) UseNumber 1.1

func (dec *Decoder) UseNumber()

UseNumber заставляет Decoder декодировать число в значение интерфейсного типа как Number, а не как float64.

type Delim 1.5

Delim — это разделитель массива или объекта JSON: один из символов [ ] { или }.

type Delim rune

func (Delim) String 1.5

func (d Delim) String() string

type Encoder

Encoder записывает значения JSON в выходной поток.

type Encoder struct {
    // contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder возвращает новый кодировщик, записывающий данные в w.

func (*Encoder) Encode

func (enc *Encoder) Encode(v any) error

Encode записывает в поток представление v в формате JSON, а затем символ новой строки.

Подробнее о преобразовании значений Go в JSON см. в документации Marshal.

func (*Encoder) SetEscapeHTML 1.7

func (enc *Encoder) SetEscapeHTML(on bool)

SetEscapeHTML задает, следует ли экранировать проблемные символы HTML внутри строк JSON в кавычках. По умолчанию символы &, < и > экранируются как \u0026, \u003c и \u003e, чтобы избежать некоторых проблем безопасности, которые могут возникнуть при встраивании JSON в HTML.

В условиях, не связанных с HTML, если экранирование ухудшает читаемость вывода, вызов SetEscapeHTML(false) отключает это поведение.

func (*Encoder) SetIndent 1.7

func (enc *Encoder) SetIndent(prefix, indent string)

SetIndent указывает кодировщику форматировать каждое последующее закодированное значение так, как если бы оно было отформатировано функцией уровня пакета Indent(dst, src, prefix, indent). Вызов SetIndent("", "") отключает отступы.

type InvalidUTF8Error

До Go 1.2 ошибка InvalidUTF8Error возвращалась функцией Marshal при попытке закодировать строковое значение с недопустимыми последовательностями UTF-8. Начиная с Go 1.2 функция Marshal вместо этого преобразует строку в допустимый UTF-8, заменяя недопустимые байты символом замены Unicode U+FFFD.

Устарело: больше не используется; оставлено для совместимости.

type InvalidUTF8Error struct {
    S string // the whole string value that caused the error
}

func (*InvalidUTF8Error) Error

func (e *InvalidUTF8Error) Error() string

type InvalidUnmarshalError

InvalidUnmarshalError описывает недопустимый аргумент, переданный функции Unmarshal. (Аргументом Unmarshal должен быть ненулевой указатель.)

type InvalidUnmarshalError struct {
    Type reflect.Type
}

func (*InvalidUnmarshalError) Error

func (e *InvalidUnmarshalError) Error() string

type Marshaler

Marshaler — это интерфейс, реализуемый типами, которые могут кодировать себя в допустимый JSON.

type Marshaler = jsonv2.Marshaler

type MarshalerError

MarshalerError представляет ошибку, возникшую при вызове метода [Marshaler.MarshalJSON] или encoding.TextMarshaler.MarshalText.

type MarshalerError struct {
    Type reflect.Type
    Err  error
    // contains filtered or unexported fields
}

func (*MarshalerError) Error

func (e *MarshalerError) Error() string

func (*MarshalerError) Unwrap 1.13

func (e *MarshalerError) Unwrap() error

Unwrap возвращает исходную ошибку.

type Number 1.1

Number представляет числовой литерал JSON.

type Number string

func (Number) Float64 1.1

func (n Number) Float64() (float64, error)

Float64 возвращает число как float64.

func (Number) Int64 1.1

func (n Number) Int64() (int64, error)

Int64 возвращает число как int64.

func (Number) MarshalJSONTo 1.27

func (n Number) MarshalJSONTo(enc *jsontext.Encoder) error

MarshalJSONTo реализует jsonv2.MarshalerTo.

func (Number) String 1.1

func (n Number) String() string

String возвращает текстовое представление числа.

func (*Number) UnmarshalJSONFrom 1.27

func (n *Number) UnmarshalJSONFrom(dec *jsontext.Decoder) error

UnmarshalJSONFrom реализует jsonv2.UnmarshalerFrom.

type Options 1.27

Options — это набор параметров, позволяющих настроить пакет v2 "json" для работы с семантикой v1 в отношении определенных возможностей. Значения этого типа можно передавать функциям v2, таким как jsonv2.Marshal или jsonv2.Unmarshal. Вместо обращения к этому типу используйте jsonv2.Options.

Рекомендации по переносу использования "json" с v1 на v2 см. в разделе "Переход на v2".

type Options = jsonopts.Options

func CallMethodsWithLegacySemantics 1.27

func CallMethodsWithLegacySemantics(v bool) Options

CallMethodsWithLegacySemantics задает вызов методов кодирования и декодирования, предоставленных типом, в соответствии с прежней семантикой:

  • При кодировании метод кодирования, объявленный для указателя-получателя, вызывается только в том случае, если значение Go адресуемо. Значения, полученные из интерфейса или элемента map, неадресуемы. Значения, полученные из указателя или элемента slice, адресуемы. Значения, полученные из элемента массива или поля структуры, наследуют адресуемость родительского значения. В отличие от этого, семантика v2 предусматривает вызов методов кодирования независимо от адресуемости.

  • При кодировании или декодировании методы Marshaler или Unmarshaler для ключей map игнорируются. Однако методы encoding.TextMarshaler или encoding.TextUnmarshaler по-прежнему могут вызываться. В отличие от этого, семантика v2 предусматривает сериализацию ключей map так же, как любых других значений (в том числе вызов методов); при этом реализация должна представить значение Go в виде строки JSON, как того требуют имена объектов JSON.

  • При кодировании, если значение ключа map реализует метод кодирования и является nil-указателем, оно сериализуется как пустая строка JSON. В отличие от этого, семантика v2 предусматривает возврат ошибки.

  • При кодировании, если интерфейсный тип реализует метод кодирования, а значение интерфейса является nil-указателем на конкретный тип, метод кодирования всегда вызывается. В отличие от этого, семантика v2 предусматривает, что методы никогда не вызываются непосредственно для значений интерфейса, а оценка откладывается до определения лежащего в основе конкретного значения. Как и для неинтерфейсных значений, для nil-указателей методы кодирования не вызываются; такие значения сериализуются как null JSON.

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func DefaultOptionsV1 1.27

func DefaultOptionsV1() Options

DefaultOptionsV1 — это полный набор всех параметров, задающих семантику v1. Он эквивалентен следующему набору логических параметров, установленных в true:

  • CallMethodsWithLegacySemantics
  • FormatByteArrayAsArray
  • FormatBytesWithLegacySemantics
  • FormatDurationAsNano
  • MatchCaseSensitiveDelimiter
  • MergeWithLegacySemantics
  • OmitEmptyWithLegacySemantics
  • ParseBytesWithLooseRFC4648
  • ParseTimeWithLooseRFC3339
  • ReportErrorsWithLegacySemantics
  • StringifyWithLegacySemantics
  • UnmarshalArrayFromAnyLength
  • jsonv2.Deterministic
  • jsonv2.FormatNilMapAsNull
  • jsonv2.FormatNilSliceAsNull
  • jsonv2.MatchCaseInsensitiveNames
  • jsontext.AllowDuplicateNames
  • jsontext.AllowInvalidUTF8
  • jsontext.EscapeForHTML
  • jsontext.EscapeForJS
  • jsontext.PreserveRawStrings

Все остальные параметры отсутствуют.

Функции Marshal и Unmarshal этого пакета семантически идентичны вызовам соответствующих функций v2 с этим параметром:

jsonv2.Marshal(v, jsonv1.DefaultOptionsV1())
jsonv2.Unmarshal(b, v, jsonv1.DefaultOptionsV1())

func FormatByteArrayAsArray 1.27

func FormatByteArrayAsArray(v bool) Options

FormatByteArrayAsArray задает форматирование [N]byte в Go как обычного массива Go, в отличие от стандартного поведения v2, при котором [N]byte форматируется с использованием кодирования двоичных данных (RFC 4648).

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func FormatBytesWithLegacySemantics 1.27

func FormatBytesWithLegacySemantics(v bool) Options

FormatBytesWithLegacySemantics задает обработку типов []~byte и [N]~byte в соответствии с прежней семантикой:

  • []~byte в Go следует обрабатывать с использованием некоторой формы кодирования двоичных данных (RFC 4648), в отличие от стандартного поведения v2, при котором так обрабатывается только []byte. В частности, v2 не рассматривает срезы именованных типов byte как двоичные данные.

  • При кодировании, если именованный тип byte реализует метод кодирования, срез сериализуется как массив JSON, состоящий из элементов, для каждого из которых вызывается метод кодирования.

  • При декодировании, если входное значение — массив JSON, []~byte декодируется как обычный срез Go. В отличие от этого, стандартное поведение v2 — возвращать ошибку при декодировании массива JSON, если ожидается некоторая форма кодирования двоичных данных.

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func FormatDurationAsNano 1.27

func FormatDurationAsNano(v bool) Options

FormatDurationAsNano задает форматирование time.Duration как числа JSON, представляющего количество наносекунд, в отличие от стандартного поведения v2, при котором возвращается ошибка.

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func MatchCaseSensitiveDelimiter 1.27

func MatchCaseSensitiveDelimiter(v bool) Options

MatchCaseSensitiveDelimiter задает, что при сопоставлении имен без учета регистра, выполняемом в рамках jsonv2.MatchCaseInsensitiveNames или параметра тега `case:ignore`, нельзя игнорировать символы подчеркивания и дефисы. Таким образом, сопоставление имен без учета регистра становится идентичным strings.EqualFold. Использование этого параметра снижает способность сопоставления без учета регистра находить распространенные варианты написания (например, "foo_bar" и "fooBar").

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func MergeWithLegacySemantics 1.27

func MergeWithLegacySemantics(v bool) Options

MergeWithLegacySemantics задает декодирование в ненулевое значение Go в соответствии с прежней семантикой:

  • При декодировании JSON null исходное значение Go сохраняется, если его тип — bool, int, uint, float, string, array или struct. В противном случае значение Go обнуляется. В отличие от этого, стандартное поведение v2 — всегда обнулять значение Go при декодировании в него JSON null.

  • При декодировании значения JSON, отличного от null, выполняется слияние с исходным значением Go для элементов массива, элементов среза, полей структуры (но не значений map), значений указателей и значений интерфейсов (только если это ненулевой указатель). Для срезов слияние выполняется с ранее существовавшими значениями элементов даже за пределами длины среза. Если исходная длина среза была больше длины массива JSON, срез усекается до соответствующего размера. В отличие от этого, стандартное поведение v2 предусматривает слияние со значениями Go для полей структур, значений map, значений указателей и значений интерфейсов. В общем случае семантика v2 выполняет слияние при декодировании объекта JSON, а в остальных случаях заменяет исходное значение.

Это влияет только на декодирование и игнорируется при кодировании. Значение по умолчанию для v1 — true.

func OmitEmptyWithLegacySemantics 1.27

func OmitEmptyWithLegacySemantics(v bool) Options

OmitEmptyWithLegacySemantics задает для параметра тега `omitempty` определение пустого значения, согласно которому поле опускается, если значение Go равно false или 0, является nil-указателем, nil-значением интерфейсного типа либо пустым массивом, срезом, map или строкой. Это переопределяет семантику v2, согласно которой поле считается пустым, если оно кодируется как JSON null или пустая строка, объект либо массив JSON.

Определения `omitempty` в v1 и v2 практически совпадают для строк, срезов, массивов и map Go. Для значений bool, int, uint, float, указателей и интерфейсов Go следует заменить использование `omitempty` на параметр тега `omitzero`, который опускает поле, если его значение равно нулевому значению Go.

Это влияет только на кодирование и игнорируется при декодировании. Значение по умолчанию для v1 — true.

func ParseBytesWithLooseRFC4648 1.27

func ParseBytesWithLooseRFC4648(v bool) Options

ParseBytesWithLooseRFC4648 задает игнорирование символов '\r' и '\n' при разборе двоичных данных, закодированных в формате "base32" или "base64". В отличие от этого, стандартное поведение v2 — возвращать ошибку, чтобы строго соблюдать раздел 3.3 RFC 4648, в котором указано, что символы, не входящие в алфавит, должны отклоняться.

Это влияет только на декодирование и игнорируется при кодировании. Значение по умолчанию для v1 — true.

func ParseTimeWithLooseRFC3339 1.27

func ParseTimeWithLooseRFC3339(v bool) Options

ParseTimeWithLooseRFC3339 задает разбор значения time.Time с нестрогим соблюдением RFC 3339. В частности, допускаются исторически некорректные представления с отклонениями в формате часа, разделителе долей секунды и представлении часового пояса. В отличие от этого, стандартное поведение v2 — строго соблюдать грамматику, заданную в RFC 3339.

Это влияет только на декодирование и игнорируется при кодировании. Значение по умолчанию для v1 — true.

func ReportErrorsWithLegacySemantics 1.27

func ReportErrorsWithLegacySemantics(v bool) Options

ReportErrorsWithLegacySemantics задает возврат ошибок функциями Marshal и Unmarshal в соответствии с прежней семантикой:

  • При кодировании или декодировании возвращаемые ошибки обычно имеют такие типы, как SyntaxError, MarshalerError, UnsupportedTypeError, UnsupportedValueError, InvalidUnmarshalError или UnmarshalTypeError. В отличие от этого, семантика v2 предусматривает, что ошибки всегда возвращаются как jsonv2.SemanticError или jsontext.SyntacticError.

  • При кодировании, если пользовательский метод кодирования возвращает ошибку, она всегда оборачивается в MarshalerError, даже если сама ошибка уже является MarshalerError, что может приводить к нескольким избыточным уровням обертки. В отличие от этого, семантика v2 предусматривает, что ошибка всегда оборачивается в jsonv2.SemanticError, если только она уже не является семантической ошибкой.

  • При декодировании, если пользовательский метод декодирования возвращает ошибку, она не оборачивается и возвращается без изменений. В отличие от этого, семантика v2 предусматривает, что ошибка всегда оборачивается в jsonv2.SemanticError, если только она уже не является семантической ошибкой.

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

  • При декодировании с jsonv2.MatchCaseInsensitiveNames, если имя объекта JSON не совпадает точно с именами нескольких полей структуры Go, ошибка не возвращается, а вместо этого используется первое объявленное поле. В отличие от этого, семантика v2 предусматривает возврат ошибки времени выполнения.

  • При декодировании синтаксическая структура входных данных JSON полностью проверяется до выполнения семантического декодирования JSON в значение Go. На практике это означает, что синтаксические ошибки во входных данных JSON не приводят к изменению целевого значения Go. В отличие от этого, семантика v2 предусматривает потоковое декодирование с постепенным декодированием входных данных JSON в целевое значение Go, поэтому при обнаружении синтаксической ошибки значение Go может быть частично изменено.

  • При декодировании семантическая ошибка не приводит к немедленному завершению процедуры: обработка продолжается. При возврате из Unmarshal сообщается только о первой семантической ошибке. В отличие от этого, семантика v2 предусматривает завершение декодирования сразу после обнаружения ошибки.

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func StringifyWithLegacySemantics 1.27

func StringifyWithLegacySemantics(v bool) Options

StringifyWithLegacySemantics задает возможность преобразования значений bool и string в строки с помощью параметра тега `string`. Этот параметр действует только для полей, тип верхнего уровня которых — bool, string, числовой тип или указатель на такой тип. В отличие от этого, стандартное поведение v2 разрешает параметр тега `string` только для типов Go, которые в противном случае сериализовались бы как число JSON, и помещает это число JSON в строку JSON. В частности, стандартное поведение v2 не преобразует значения bool и string Go в строки. Если ReportErrorsWithLegacySemantics равен false, некорректное использование `string` приводит к ошибке времени выполнения.

При кодировании такие значения Go сериализуются в обычном для них представлении JSON, заключенном в строку JSON. При декодировании такие значения Go должны десериализоваться из строки JSON, содержащей их обычное представление JSON или представление числа Go для соответствующего числового типа. Обратите внимание, что грамматика чисел Go шире грамматики чисел JSON. JSON null, заключенный в строку JSON, является допустимой заменой JSON null при декодировании в значение Go, к которому применяется `string`. В отличие от этого, стандартное поведение v2 отклоняет строковые представления чисел, не соответствующие грамматике числа JSON, а также JSON null, заключенный в строку JSON.

Это влияет как на кодирование, так и на декодирование. Значение по умолчанию для v1 — true.

func UnmarshalArrayFromAnyLength 1.27

func UnmarshalArrayFromAnyLength(v bool) Options

UnmarshalArrayFromAnyLength задает возможность декодирования массивов Go из входных массивов JSON любой длины. Если массив JSON слишком короткий, оставшиеся элементы массива Go обнуляются. Если массив JSON слишком длинный, лишние элементы массива JSON пропускаются. В отличие от этого, стандартное поведение v2 требует, чтобы массив Go декодировался из входного массива JSON точно такой же длины.

Это влияет только на декодирование и игнорируется при кодировании. Значение по умолчанию для v1 — true.

type RawMessage

RawMessage — это значение JSON в необработанном закодированном виде. Он реализует интерфейсы Marshaler и Unmarshaler и может использоваться для отложенного декодирования JSON или предварительного вычисления представления JSON.

type RawMessage = jsontext.Value

Пример (кодирование)

В этом примере RawMessage используется для включения предварительно вычисленного JSON при кодировании.

Код:

h := json.RawMessage(`{"precomputed": true}`)

c := struct {
    Header *json.RawMessage `json:"header"`
    Body   string           `json:"body"`
}{Header: &h, Body: "Hello Gophers!"}

b, err := json.MarshalIndent(&c, "", "\t")
if err != nil {
    fmt.Println("error:", err)
}
os.Stdout.Write(b)

Вывод:

{
	"header": {
		"precomputed": true
	},
	"body": "Hello Gophers!"
}

Пример (декодирование)

В этом примере RawMessage используется для отложенного разбора части сообщения JSON.

Код:

type Color struct {
    Space string
    Point json.RawMessage // delay parsing until we know the color space
}
type RGB struct {
    R uint8
    G uint8
    B uint8
}
type YCbCr struct {
    Y  uint8
    Cb int8
    Cr int8
}

var j = []byte(`[
    {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
    {"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255}}
]`)
var colors []Color
err := json.Unmarshal(j, &colors)
if err != nil {
    log.Fatalln("error:", err)
}

for _, c := range colors {
    var dst any
    switch c.Space {
    case "RGB":
        dst = new(RGB)
    case "YCbCr":
        dst = new(YCbCr)
    }
    err := json.Unmarshal(c.Point, dst)
    if err != nil {
        log.Fatalln("error:", err)
    }
    fmt.Println(c.Space, dst)
}

Вывод:

YCbCr &{255 0 -10}
RGB &{98 218 255}

type SyntaxError

SyntaxError описывает синтаксическую ошибку JSON. Unmarshal возвращает SyntaxError, если не удается разобрать JSON.

type SyntaxError struct {
    Offset int64 // error occurred after reading Offset bytes
    // contains filtered or unexported fields
}

func (*SyntaxError) Error

func (e *SyntaxError) Error() string

type Token 1.5

Token содержит значение одного из следующих типов:

  • Delim — для четырех разделителей JSON [ ] { }
  • bool — для логических значений JSON
  • float64 — для чисел JSON
  • Number — для чисел JSON
  • string — для строковых литералов JSON
  • nil — для JSON null
type Token any

type UnmarshalFieldError

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

Устарело: больше не используется; оставлено для совместимости.

type UnmarshalFieldError struct {
    Key   string
    Type  reflect.Type
    Field reflect.StructField
}

func (*UnmarshalFieldError) Error

func (e *UnmarshalFieldError) Error() string

type UnmarshalTypeError

UnmarshalTypeError описывает значение JSON, неподходящее для значения определенного типа Go.

type UnmarshalTypeError struct {
    Value  string       // description of JSON value - "bool", "array", "number -5"
    Type   reflect.Type // type of Go value it could not be assigned to
    Offset int64        // error occurred after reading Offset bytes; added in Go 1.5
    Struct string       // name of the root type containing the field; added in Go 1.8
    Field  string       // the full path from root node to the value; added in Go 1.8
    Err    error        // may be nil; added in Go 1.27
}

func (*UnmarshalTypeError) Error

func (e *UnmarshalTypeError) Error() string

func (*UnmarshalTypeError) Unwrap 1.27

func (e *UnmarshalTypeError) Unwrap() error

type Unmarshaler

Unmarshaler — это интерфейс, реализуемый типами, которые могут декодировать JSON-представление самих себя. Можно считать, что входные данные представляют собой допустимое кодирование значения JSON. UnmarshalJSON должен скопировать данные JSON, если требуется сохранить их после возврата.

type Unmarshaler = jsonv2.Unmarshaler

type UnsupportedTypeError

UnsupportedTypeError возвращается функцией Marshal при попытке закодировать значение неподдерживаемого типа.

type UnsupportedTypeError struct {
    Type reflect.Type
}

func (*UnsupportedTypeError) Error

func (e *UnsupportedTypeError) Error() string

type UnsupportedValueError

UnsupportedValueError возвращается функцией Marshal при попытке закодировать неподдерживаемое значение.

type UnsupportedValueError struct {
    Value reflect.Value
    Str   string
}

func (*UnsupportedValueError) Error

func (e *UnsupportedValueError) Error() string

Подкаталоги

Имя Краткое описание
..
jsontext Пакет jsontext реализует синтаксическую обработку JSON, как указано в RFC 4627, RFC 7159, RFC 7493, RFC 8259 и RFC 8785.
v2 Пакет json реализует семантическую обработку JSON, как указано в RFC 8259.

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/encoding/json/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API