[英]How can I turn map[string]interface{} to different type of struct?
[英]Can I add a field to an interface using a struct?
我遇到了一个有趣的场景。 我有一个结构,我想向它添加一个字段消息。 我可以通过Can I add a field to an existing struct with Go? .
type User struct {
// user fields here
}
type UpdationResponse struct {
User
Message string `json:"message,omitempty"`
}
func SendSuccessResponse(w http.ResponseWriter, r *http.Request, resp interface{}) interface{} {
w.Header().Set("Content-Type", "application/json")
return json.NewEncoder(w).Encode(resp)
}
这将返回 JSON 之类的
{
"id": "50",
"firstName": "vibhor",
"lastName": "agrawal",
"email": "someemail@emailprovider.com",
"isVerified": false,
"joinedAt": "2020-06-28T09:45:59Z",
"fullName": "vibhor agrawal"
"message": "Profile Updated."
}
因此,这有助于我发送用户数据以及一条消息,比如“配置文件已更新。”。 如果我想对我所有的 API 进行概括。 有什么我可以做的。
我试过了:
type SuccessResponse struct {
Data interface{}
Message string `json:"message,omitempty"`
}
func SendSuccessResponse(w http.ResponseWriter, r *http.Request, resp SuccessResponse) interface{} {
w.Header().Set("Content-Type", "application/json")
return json.NewEncoder(w).Encode(resp)
}
但是当我将它作为 JSON 发送时,它的结构类似于
{
"Data": {
"id": "50",
"firstName": "vibhor",
"lastName": "agrawal",
"email": "someemail@emailprovider.com",
"isVerified": false,
"joinedAt": "2020-06-28T09:45:59Z",
"fullName": "vibhor agrawal"
},
"message": "Profile Updated."
}
有没有一种方法可以在数据本身中添加消息并将其概括为我所有的成功响应而不管Data
?
简而言之:这是不可能的。
长答案:
在您的第一个示例中, struct UpdationResponse
扩展了 struct User
。 这也称为混合。 简单地说UpdationResponse
获取User
的所有属性并自己使用它们。
在您的第二个示例中,结构SuccessResponse
定义了可以是任何内容的属性Data
。 Data
是SuccessResponse
的子元素,因此会被编组。 没有办法绕过它,因为 go 源代码是静态类型的并提前编译。
您可以让响应实现json.Marshaler
接口,让它分别编组这两个字段,然后在最后合并结果。
func (r Response) MarshalJSON() ([]byte, error) {
out1, err := json.Marshal(r.Data)
if err != nil {
return nil, err
}
type _Response Response // to avoid infinite recursion
out2, err := json.Marshal((_Response)(r))
if err != nil {
return nil, err
}
// NOTE: this may need more work to handle other cases, for example
// the Data field's dynamic type being a slice of some type, rather than
// a single struct....
if size := len(out1); size > 0 && out1[size-1] == '}' {
if size > 2 {
out1[size-1] = ',' // replace "}" with ","
} else {
out1 = out1[:size-1] // drop "}"
}
out2 = out2[1:] // drop "{"
out := append(out1, out2...) // merge
return out, nil
}
return out2, nil
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.