Названия ключей JSON в нижнем регистре с помощью JSON Marshal в Go

175

Я хочу использовать "encoding/json"пакет, чтобы упорядочить структуру, объявленную в одном из импортированных пакетов моего приложения.

Например.:

type T struct {
    Foo int
}

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

out, err := json.Marshal(&T{Foo: 42})

приведет к

{ "Foo": 42}

но я хочу получить

{ "Foo": 42}

Можно ли обойти проблему каким-то простым способом?

Anisus
источник
5
@Zippoxer: я бы сказал: ключ в протоколе связи клиент / сервер, строго определенный для строчных букв. Ну, в моем случае это не имеет значения, так как я сам определил протокол ... но по крайней мере в теории? Но я знаю, что в основном я трачу слишком много времени на глупые мелочи.
ANisus
Не извиняйся. Вы не глупый, язык, который не принимает полную спецификацию json, является глупым (хотя проблема легко решается, как показано ниже).
Джехан
@ANisus: Я неправильно понял ваш вопрос, касающийся имен структурных ключей, а не имен ключей JSON. Отказался от голосования.
Хлипкий

Ответы:

266

Посмотрите документы для кодирования / json.Marshal . В нем обсуждается использование тегов struct field для определения того, как сгенерированный json отформатирован.

Например:

type T struct {
    FieldA int    `json:"field_a"`
    FieldB string `json:"field_b,omitempty"`
}

Это сгенерирует JSON следующим образом:

{
    "field_a": 1234,
    "field_b": "foobar"
}
jimt
источник
8
Полевые теги? Боже мой ... Я пропустил всю эту часть при поиске в документах. Я искал флаги, функции или некоторые другие настройки. Ну, это именно тот ответ, который я искал! И, кроме того, у меня есть новая концепция Go для изучения: теги полей :)
ANisus
Они довольно удобны. Вы можете получить к ним доступ во время выполнения через reflectпакет.
Джимт
Да, когда я работаю с отражением, я вижу, как способ добавить метаданные в поле может быть замечательной вещью! Кстати, только что попробовал ответ. Работает как шарм.
ANisus
5
Я только начал ругать язык go - насколько это глупо, зачем им создавать поля с строчными буквами в сгенерированном JSON и т. Д., И т. Д. Затем я наткнулся на эту тему и подумал: «OMG Это великолепно !!!». Я даже вскочил и объяснил своей девушке, почему я так взволнован: D Это так круто :)))
nyxz
11
Убедитесь, что между двоеточием и первой кавычкой тега нет пробела! Используйте json:"some_tag"вместо json: "some_tag". Я получил немного на некоторое время.
Дэвид Моралес
8

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

Лили Баллард
источник
Глупо то, что другой пакет (содержащий типы) на самом деле тоже мой. Но, да, я, наверное, слепо смотрел на то, что это должна быть структура. Использование map[string]interface{}будет работать до тех пор, пока я не
получу
1
@ ANisus: О, мой ответ основывался на том, что вы не контролируете определение структуры. Ответ Джимта определенно то, что вы хотите.
Лили Баллард
Да, мне не было ясно, был ли это внешний пакет или нет. Но ваш ответ по-прежнему актуален и полезен в тех случаях, когда вы не контролируете определения.
ANisus