dsjws44266
dsjws44266
2017-07-08 19:17
浏览 78

编码为JSON时,Golang错误类型为空

I'm trying to encode some JSON for a REST api, everything is working fine except for some errors. For example, with this struct:

type TemplateResponse struct {
    Message string
    Error   error
    Template Template
}

Encoded with this data:

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)

Returns:

{
  "Message": "Template not found.",
  "Error": {},
  "Template": {
    "Name": "",
    "Disabled": false,
    "Path": "",
    "Version": ""
  }
}

I'm getting this seemingly randomly across my application, where 'error' types are being returned as empty. Any ideas?

Thanks!

图片转代码服务由CSDN问答提供 功能建议

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

  type TemplateResponse结构{
消息字符串
错误错误
模板模板
} 
    
 
 

使用以下数据编码:

  res:= TemplateResponse {“找不到模板。”,fmt.Errorf(“此主机上没有模板 名称为“ + vars [“ name”]),模板{}} 
json.NewEncoder(w).Encode(res)
   
 
 

返回:

  {
“消息”:“找不到模板。”,
“错误”:{},
“模板”:{
“名称”:“”  ,
“ Disabled”:false,
“ Path”:“”,
“ Version”:“” 
} 
} 
   
 
 

I 在我的应用程序中,这似乎是随机的,其中“错误”类型返回为空。 有什么想法吗?

谢谢!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dongnong3799
    dongnong3799 2017-07-08 19:31
    已采纳

    Because error is just an interface. It may hold a value of any concrete type that implements it.

    In your example you used fmt.Errorf() to create an error value. That calls errors.New() which returns a pointer to a value of the unexported errors.errorString struct. Its definition is:

    type errorString struct {
        s string
    }
    

    This struct value will be marshaled, but since it has no exported fields (only exported fields are marshaled), it will be an empty JSON object: {}.

    The "fix" is: don't marshal values of "general" interfaces, relying on that the dynamic values can be marshaled into JSON meaningfully. Instead you should add a field that stores the error string (the result of error.Error()), and omit the Error error field from marshaling, e.g.:

    type TemplateResponse struct {
        Message  string
        Error    error `json:"-"`
        ErrorMsg string
        Template Template
    }
    

    Of course then you also need to set / fill the ErrorMsg field before marshaling.

    Or if you don't need to store the error value in the struct, remove that field completely:

    type TemplateResponse struct {
        Message  string
        ErrorMsg string
        Template Template
    }
    

    If you still want to keep the Error error field (and not the ErrorMsg field), then you need to implement a custom marshaling logic by implementing the json.Marshaler interface where you can "convert" the error value to a meaningful string for example (or into another value that can be marshaled properly).

    点赞 评论

相关推荐