Типы ошибок Golang пусты при кодировании в JSON

#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. Имеет смысл. Большое спасибо за отличное объяснение!