我正在尝试为REST API编码一些JSON,除某些错误外,其他所有东西都工作正常。例如,使用此结构:

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": ""
  }
}

我在我的应用程序中似乎是随机得到的,其中“错误”类型返回为空。有任何想法吗?

谢谢!

最佳答案

因为 error 只是一个接口(interface)。它可以保存实现它的任何具体类型的值。

在您的示例中,您使用 fmt.Errorf() 创建了error值。这将调用 errors.New() ,该返回的指针指向未导出的errors.errorString结构的值。其定义是:

type errorString struct {
    s string
}

该struct值将被封送,但由于它没有导出的字段(仅封送了已导出的字段),因此它将是一个空的JSON对象:{}

“解决方案”是:不要封送“通用”接口(interface)的值,这取决于可以将动态值有意义地编码到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 接口(interface)来实现自定义封送处理逻辑,在该接口(interface)中,您可以将error值“转换”为有意义的string,例如(或转换为另一个)可以正确封送的值)。

08-04 22:35
查看更多