json - 有没有办法在不为空时将不同的结构类型编组到相同的 json 字段?
问题描述
我在这样的通用包中定义了一个响应结构。
package main
import (
"encoding/json"
"fmt"
)
type Response struct {
Id string `json:"id,omitempty"`
//All other int/string fields
NestedObj *Nested `json:"nested,omitempty"`
}
type Nested struct {
//Field causing the issue.
ExtendedString string `json:"extended,omitempty"` //some user will need/expect a string
//Other user need extended json field as a different object
Extended *Extended `json:"extended,omitempty"` //changing json:extended to other json:extended1 will work as expected
//But need to have the same field name containing object or just a string field
}
type Extended struct {
OtherField string `json:"another,omitempty"`
}
func main() {
response := &Response{Id: "UNIQUE_ID"}
response.NestedObj = &Nested{}
//Part 1
response.NestedObj.ExtendedString = "value"
b, err := json.Marshal(response)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(b))
//Part 1 end
response1 := &Response{Id: "UNIQUE_ID"}
response1.NestedObj = &Nested{}
//Part 2
response1.NestedObj.Extended = &Extended{}
response1.NestedObj.Extended.OtherField = "value"
b1, err := json.Marshal(response1)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(b1))
//Part 2 end
//Either Part 1 or 2 will be set for user type as per preference/flag/condition.
}
现在,由于我在 struct 中使用指针来不导出 json 中的任何空字段/对象,所以我想表现得像当我设置ExtendedString
为某个字符串值并省略Extended
自定义结构时,我的 json 应该看起来像
{"id":"UNIQUE_ID",...other json fields..., "nested":{"extended": "value"}}
但是当我设置Extended
struct ignoringExtendedString
我应该得到 json 作为
{"id":"UNIQUE_ID",...other json fields..., "nested":{"extended": {"another":"value"}}}
if
可以肯定的是,根据用户偏好(或switch
条件可能),在编组的 json 中将需要其中任何一个,因为它们必须具有字段名称,extended
该名称可以是字符串或包含其他字段的 json 对象。
是否可以在不复制主结构的情况下实现这一点?
解决方案
json.Marshal
MarshalJSON
如果存在,将调用您的类型方法。使用它,您可以检查您的条件,然后返回相应的 JSON。
package main
import (
"fmt"
"encoding/json"
)
type ExtendedObj struct {
Value string `json:"another"`
}
type Extended struct {
str string
Obj ExtendedObj `json:"extended"`
}
func (e* Extended) MarshalJSON() ([]byte, error) {
if e.str != "" {
return json.Marshal(struct {
Value string `json:"extended"`
}{e.str})
}
return json.Marshal(e)
}
func main() {
v1 := Extended{"Hey!", ExtendedObj{}}
jsonBytes, err := json.Marshal(&v1)
if err != nil {
fmt.Println("Error", err)
}
fmt.Println(string(jsonBytes))
v2 := Extended{"", ExtendedObj{"Hey!"}}
jsonBytes2, err := json.Marshal(v2)
fmt.Println(string(jsonBytes2))
}
推荐阅读
- html - 如何在css中居中多个按钮?
- javascript - 如何将选择链接到我的表头?
- python - 是否可以访问先前训练的 tensorflow 模型?
- python - python可以规范化对象数组吗?
- python - 如何更新子图?
- c# - 获取放置在图像中的组件的新位置
- flutter - 在 Flutter 的 Textfield 中单击电话后退按钮后,如何在 Flutter 上隐藏输入键盘?
- ios - 禁用屏幕轨道的自动 Firebase 分析
- java - 在 saucelabs 云设备中运行 appium 更改公共 IP 以进行特定国家/地区的应用程序测试
- python - Python:如果光标处于非活动状态五分钟,如何控制光标并在用户触摸鼠标时暂停程序(我的 python 程序)?