Я создал API в Go, который после вызова выполняет запрос, создает экземпляр структуры и затем кодирует эту структуру как JSON перед отправкой обратно вызывающей стороне. Теперь я бы хотел, чтобы вызывающая сторона могла выбрать конкретные поля, которые они хотели бы вернуть, передав параметр GET «fields».
Это означает, что в зависимости от значений полей моя структура изменится. Есть ли способ удалить поля из структуры? Или, по крайней мере, динамически скрывать их в ответе JSON? (Примечание: иногда у меня есть пустые значения, поэтому тег JSON omitEmpty здесь не будет работать) Если ни один из них не возможен, есть ли предложение по лучшему способу обработки этого? Заранее спасибо.
Ниже приведена уменьшенная версия структур, которые я использую:
type SearchResult struct {
Date string `json:"date"`
IdCompany int `json:"idCompany"`
Company string `json:"company"`
IdIndustry interface{} `json:"idIndustry"`
Industry string `json:"industry"`
IdContinent interface{} `json:"idContinent"`
Continent string `json:"continent"`
IdCountry interface{} `json:"idCountry"`
Country string `json:"country"`
IdState interface{} `json:"idState"`
State string `json:"state"`
IdCity interface{} `json:"idCity"`
City string `json:"city"`
} //SearchResult
type SearchResults struct {
NumberResults int `json:"numberResults"`
Results []SearchResult `json:"results"`
} //type SearchResults
Затем я закодирую и выведу ответ примерно так:
err := json.NewEncoder(c.ResponseWriter).Encode(&msg)
Ответы:
РЕДАКТИРОВАТЬ: я заметил несколько отрицательных голосов и еще раз взглянуть на этот вопрос и ответы. Кажется, что большинство людей упускают из виду, что ОП просил динамически выбирать поля на основе списка полей, предоставленного вызывающим абонентом. Вы не можете сделать это с помощью статически определенного тега структуры json.
Если вы хотите всегда пропустить поле для json-кодирования, тогда, конечно, используйте его,
json:"-"
чтобы игнорировать поле (также обратите внимание, что это не требуется, если ваше поле не экспортировано - эти поля всегда игнорируются кодером json). Но это не вопрос ОП.Цитировать комментарий к
json:"-"
ответу:В этом случае я бы использовал интерфейс map [string] {} вместо struct. Вы можете легко удалить поля, вызвав
delete
встроенные на карту поля для удаления.То есть, если вы не можете запросить только запрашиваемые поля в первую очередь.
источник
map[string]interface{}
имеет смысл, но не требует, чтобы вы отбрасывали определение типа.Id
но я не хочу возвращать всю структуру json. Спасибо за это!используйте `json:" - "`
документ: http://golang.org/pkg/encoding/json/#Marshal
источник
Другой способ сделать это - иметь структуру указателей с
,omitempty
тегом. Если указатели равны нулю , поля не будут маршаллическими.Этот метод не потребует дополнительного отражения или неэффективного использования карт.
Тот же пример, что и у jorelli, использующего этот метод: http://play.golang.org/p/JJNa0m2_nw
источник
Вы можете использовать
reflect
пакет для выбора нужных полей, отражая теги полей и выбираяjson
значения тегов. Определите метод на вашем SearchResults типа , который выбирает нужные поля и возвращают их в видеmap[string]interface{}
, а затем маршал , что вместо того , чтобы в SearchResults STRUCT себя. Вот пример того, как вы можете определить этот метод:и вот работоспособное решение, которое показывает, как вы будете вызывать этот метод и упорядочить свой выбор: http://play.golang.org/p/1K9xjQRnO8
источник
Я только что опубликовал шериф , который преобразует структуры в карту на основе тегов, помеченных на полях структуры. Затем вы можете выполнить маршал (JSON или другие) сгенерированной карты. Вероятно, он не позволяет вам сериализовать только набор полей, запрошенных вызывающей стороной, но я предполагаю, что использование набора групп позволит вам охватить большинство случаев. Использование групп вместо полей напрямую, скорее всего, также увеличит возможности кеширования.
Пример:
источник
Возьмите три ингредиента:
reflect
Пакет перебрать всех полей структуры.if
Заявление , чтобы забрать поля , которые вы хотитеMarshal
, иencoding/json
ПакетMarshal
полей по своему вкусу.Приготовление:
Смешайте их в хорошей пропорции. Используйте
reflect.TypeOf(your_struct).Field(i).Name()
для получения имениi
поляyour_struct
.Используйте,
reflect.ValueOf(your_struct).Field(i)
чтобы получить типовоеValue
представление поляi
thyour_struct
.Использование
fieldValue.Interface()
для получения фактического значения (upcasted к типу интерфейса {}) изfieldValue
типаValue
(обратите внимание на использование кронштейна - интерфейс () метод производитinterface{}
Если вам, к счастью, удастся не сжечь транзисторы или автоматические выключатели, вы должны получить что-то вроде этого:
Обслуживание:
служить с произвольной структурой и
map[string]bool
полями, которые вы хотите включить, напримерПриятного аппетита!
источник
Вы можете использовать теговый атрибут "omitifempty" или сделать необязательные поля указателями и оставить те, которые вы хотите пропустить, неинициализированными.
источник
Я также столкнулся с этой проблемой, сначала я просто хотел специализировать ответы в моем http-обработчике. Моим первым подходом было создание пакета, который копирует информацию о структуре в другую структуру, а затем упорядочивает эту вторую структуру. Я сделал этот пакет, используя рефлексию, поэтому мне никогда не нравился такой подход, и при этом я не был динамически.
Поэтому я решил изменить пакет encoding / json, чтобы сделать это. Функции
Marshal
,MarshalIndent
и(Encoder) Encode
дополнительно получаетtype F map[string]F
Я хотел смоделировать JSON полей, которые необходимы для маршалинга, поэтому он только маршалирует поля, которые находятся на карте.
https://github.com/JuanTorr/jsont
источник
Сейчас этот вопрос немного устарел, но я столкнулся с той же проблемой некоторое время назад, и, поскольку я не нашел простого способа сделать это, я создал библиотеку для этой цели. Это позволяет легко генерировать
map[string]interface{}
из статической структуры.https://github.com/tuvistavie/structomap
источник
[]byte
заключается в том, что он не очень многократно используется: например, нет простого способа добавить поле впоследствии. Поэтому я бы предложил создатьmap[string]interface{}
сериализацию JSON и включить ее в стандартную библиотеку.У меня не было той же проблемы, но похожей. Приведенный ниже код решает и вашу проблему, конечно, если вы не против проблемы производительности. Перед внедрением такого решения в вашей системе, я рекомендую вам изменить структуру, если вы можете. Отправка ответа переменной структуры является чрезмерной. Я полагаю, что структура ответа представляет собой контракт между запросом и ресурсом, и это не должно быть зависимым запросом (я могу сделать ненужные поля пустыми). В некоторых случаях нам приходится реализовывать этот дизайн, если вы считаете, что именно в этих случаях вот ссылка на игру и код, который я использую.
источник
Я создал эту функцию для преобразования структуры в строку JSON, игнорируя некоторые поля. Надеюсь, это поможет.
Пример: https://play.golang.org/p/nmq7MFF47Gp
источник
Вот как я определил свою структуру.
И внутри моей функции
user.Password = nil
не быть маршалом.источник