Как контролировать поведение Go при кодировании данных JSON

Go

Сегодня давайте поговорим о трех проблемах и решениях, которые я столкнулся с большинством, когда JSON кодирует данные в ходу. Посмотрим, если вы поцарапали много волос для этих проблем.

Пользовательское имя ключа JSON

Я не решался добавить этот вопрос в статью, потому что в принципе все могут, но я все же поставил его в таком же вопросе.Для новых контактовGoодноклассники дружнее.

Начнем с самой распространенной проблемы: во-первых, при кодировании данных в формат JSON в программе Go мы обычно сначала определяем тип структуры и сохраняем данные в структурной переменной.

type Address struct {
    Type    string
    City    string  
    Country string
}

type CreditCard struct {
    FirstName string
    LastName  string
    Addresses []*Address
    Remark    string
}

home := &Address{"private", "Aartselaar", "Belgium"}
office := &Address{"work", "Boom", "Belgium"}
card := VCard{"Jan", "Kersschot", []*Address{home, office}, "none"}

js, err := json.Marshal(card)
fmt.Printf("JSON format: %s", js)

Кодируются только экспортированные элементы структуры, поэтому мы решили начинать имена полей с заглавной буквы. При кодировании имя поля структуры по умолчанию используется как имя в объекте JSON.key, а вообще дается JSONHTTP接口Для возврата данных в спецификации интерфейса обычно требуется возвращать данные.snake caseимя поля стиля. Решение этой проблемы заключается в настройке соответствующих полей в метке поля структуры при объявлении структуры.JSON key

Таким образом, мы можем изменить объявление структуры на следующее:

type Address struct {
    Type    string  `json:"type"`
    City    string  `json:"city"`
    Country string  `json:"country"`
}

Игнорировать указанные поля при кодировании JSON

Не все данные, которые мы ожидаем закодировать вJSONоткрыты для внешних интерфейсов, поэтому для некоторых конфиденциальных полей мы часто хотим извлечь их из закодированногоJSONигнорируются в данных. Затем он также сказал, что будут закодированы только экспортированные элементы структуры.Некоторые студенты будут просить меня напрямую использовать имена полей в нижнем регистре? Однако доступ к неэкспортируемым полям возможен только внутри пакета.Такие внутренние конфиденциальные данные часто являются базовыми данными приложения, которые предоставляются публичным пакетом проекта. Итак, как мы можем не только сохранить экспортоспособность поля, но и сделать его вJSONИгнорируется ли это в данных? Или используйте метку структуры для аннотирования, например структуру, определенную ниже, вы можете использовать удостоверение личностиIdCardполе вJSONУдалено из данных:

type User struct {
    Name    string  `json:"name"`
    Age     Int     `json:"int"`
    IdCard  string  `json:"-"`
}

encoding/jsonУправление данными через теги полей структуры указано в исходном коде и в документации.JSONОбъяснение поведения кодирования:

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

// 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"`

omitemptyЭто когда данные поля пусты, вJSONЭто поле отсутствует в . В целях экономии места для данных,ProtobufКаждая метка поля в коде структуры, сгенерированном компилятором, имеетomitempty. Но когдаApiЭто обычно не используется в разработке, потому что поле не фиксировано и очень недружественно для внешнего интерфейса.

правильноProtobufЕсли вы не поняли, вы можете прочитать мою предыдущую статью "Руководство по языку Protobuf".

Структура метки поляjsonНе добавлять аннотацииomitemptyПозже возникает ситуация, когда поле с типом данных slice будет удалено, когда данные будут пустыми.JSONзакодировано какnullвместо[]. Этот интерфейс часто спрашивает меня, могу ли я вернуться, когда у меня нет данныхnull, и каждый раз записывайте еще одно суждение. Моя риторика нет, на самом деле норма в том, что мы должны вернуться[]Знания я сам не нашел решения. Для тех, кто страдает обсессивно-компульсивным расстройством при написании кода или хочет разобраться в этой проблеме, хорошие новости за один деньStackOverflowЯ видел ответ выше, но обнаружил, что это было вызвано небрежностью кодирования.

Решать пустые ломтики кодированы как NULL в JSON в

Поскольку нулевое значение среза равноnil, без адреса в памяти, поэтому при определении в этой формеvar f []intинициализацияsliceПосле этого закодируйте его в JSON какnull, если вы хотите закодировать пустой фрагмент в JSON как[]Затем вам нужно использовать make для инициализации слайса, чтобы выделить для него адреса памяти:

Выполнение следующего примера показывает разницу между двумя точками:

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Friends []string
}

func main() {
	var f1 []string
	f2 := make([]string, 0)

	json1, _ := json.Marshal(Person{f1})
	json2, _ := json.Marshal(Person{f2})

	fmt.Printf("%s\n", json1)
	fmt.Printf("%s\n", json2)
}

выход:

{"Friends":null}
{"Friends":[]}

На самом деле, причиной этой проблемы являетсяappendфункции (бросание горшка), все мы знаем, что после определения переменных ссылочного типа, если они не инициализированы, их значенияnil, без адреса, указывающего на память, нельзя использовать напрямую. ноappendПри добавлении элементов в слайс функция определяет, был ли слайс инициализирован, и если нет, то инициализирует и выделяет для него базовый массив. Моя привычка — сначала объявлять срез, а затем добавлять элементы к срезу в приведенном ниже коде цикла. Но если цикл не выполняется, например, вы не находите данные в базе данных, это приведет к возврату соответствующего поля среза при отсутствии данных.nilтогда будьJSONзакодировано какnull. так это итог опытаTipВы должны быть осторожны при написании кода.

Вот как я кодирую данные по мере разработкиJSONТри проблемы, возникшие в формате, и соответствующие решения. Плюс то, что было написано ранееСтатья о парсинге JSON, две статьи вместе могут почти суммировать ежедневное развитиеencoding/jsonРазличные проблемы с использованием библиотеки.

Отсканируйте QR-код под кодом и подпишитесь на официальный аккаунт, чтобы как можно скорее получать ценные технические оригинальные статьи.