#go
#json #Вперед #структура
Вопрос:
Я пытаюсь закодировать некоторый JSON для REST api, все работает нормально, за исключением некоторых ошибок. Например, с помощью этой структуры:
type TemplateResponse struct {
Message string
Error error
Template Template
}
Закодировано с помощью этих данных:
res := TemplateResponse{"Template not found.", fmt.Errorf("There is no template on this host with the name " vars["name"]), Template{}}
json.NewEncoder(w).Encode(res)
ВОЗВРАТ:
{
"Message": "Template not found.",
"Error": {},
"Template": {
"Name": "",
"Disabled": false,
"Path": "",
"Version": ""
}
}
Я получаю это, по-видимому, случайным образом в своем приложении, где типы «ошибок» возвращаются как пустые. Есть идеи?
Спасибо!
Ответ №1:
Потому error
что это просто интерфейс. Он может содержать значение любого конкретного типа, который его реализует.
В вашем примере вы использовали fmt.Errorf()
для создания error
значения. Это вызывает errors.New()
, который возвращает указатель на значение неэкспортированной errors.errorString
структуры. Его определение:
type errorString struct {
s string
}
Это значение структуры будет маршалировано, но поскольку оно не имеет экспортированных полей (маршалируются только экспортированные поля), это будет пустой объект JSON : {}
.
«Исправление» заключается в следующем: не маршалируйте значения «общих» интерфейсов, полагаясь на то, что динамические значения могут быть маршалированы в JSON осмысленно. Вместо этого вы должны добавить поле, в котором хранится строка ошибки (результат error.Error()
), и исключить Error error
поле из маршалинга, например:
type TemplateResponse struct {
Message string
Error error `json:"-"`
ErrorMsg string
Template Template
}
Конечно, тогда вам также необходимо установить / заполнить ErrorMsg
поле перед маршалингом.
Или, если вам не нужно сохранять error
значение в структуре, полностью удалите это поле:
type TemplateResponse struct {
Message string
ErrorMsg string
Template Template
}
Если вы все еще хотите сохранить Error error
поле (а не ErrorMsg
поле), то вам необходимо реализовать пользовательскую логику маршалинга, реализовав json.Marshaler
интерфейс, в котором вы можете «преобразовать» error
значение string
, например, в значимое (или в другое значение, которое можно маршалировать должным образом).
Комментарии:
1. Имеет смысл. Большое спасибо за отличное объяснение!