Типы ошибок Golang пусты, когда закодированы в 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 значение в struct, полностью удалите это поле:

type TemplateResponse struct {
    Message  string
    ErrorMsg string
    Template Template
}

если вы все еще хотите сохранить Error error поле (а не ErrorMsg поле), то вам нужно реализовать пользовательскую логику маршалинга, реализуя json.Marshaler интерфейс, где вы можете "преобразовать"error значение для значимого string например (или в другое значение, которое может быть передан правильно).