如何忽略结构的 MarshalJSON 实现(带有嵌套结构)?
How to ignore MarshalJSON implementation of a struct (with nested structs)?
是否可以忽略结构的自定义 MarshalJSON
实现,
并只使用标准编组函数?
结构复杂,嵌套结构很多,都是
使用自定义 MarshalJSON
,我想忽略它们。
感觉应该是微不足道的。你有什么想法吗?
一些细节
创建新类型的明显解决方案效果不佳,因为嵌套结构仍然使用它们的 MarshalJSON
s。
代码示例如下:
func (de DeploymentExtended) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if de.Location != nil {
objectMap["location"] = de.Location
}
if de.Properties != nil {
objectMap["properties"] = de.Properties
}
if de.Tags != nil {
objectMap["tags"] = de.Tags
}
return json.Marshal(objectMap)
}
还有很多属性(如 Name
等),我希望在我的 JSON 中看到这些属性(Properties
和其他嵌套结构也是如此) .
此代码的 Python 实现提供了该数据,我的软件使用它,我(将代码移植到 Go)也希望能够从我的 Go 程序中导出这些数据。
您可以通过两种方式执行此操作:
- 自定义类型(隐藏
MarshalJSON
方法);或
- 自定义编组器(使用
reflect
在运行时忽略任何 MarshalJSON
方法)
自定义类型
例如,采用这些嵌套类型:
type Y struct {
FieldZ string
}
type X struct {
Name string
Y Y
}
func (x *X) MarshalJSON() ([]byte, error) { return []byte(`"DONT WANT THIS"`), nil }
func (y *Y) MarshalJSON() ([]byte, error) { return []byte(`"DEFINITELY DONT WANT THIS"`), nil }
需要隐藏这些类型以避免调用不需要的 MarshalJSON
方法:
type shadowY struct {
FieldZ string
}
type shadowX struct {
Name string
Y shadowY
}
//
// transform original 'x' to use our shadow types
//
x2 := shadowX{
Name: x.Name,
Y: shadowY(x.Y),
}
https://go.dev/play/p/vzKtb0gZZov
反思
这是一个简单的基于 reflect
的 JSON 封送拆收器来实现您想要的。它假定所有自定义编组器都使用指针接收器 - 并取消引用指针,因此标准库的 json.Marshal
不会“看到”它们:
func MyJSONMarshal(v interface{}) (bs []byte, err error) {
k := reflect.TypeOf(v).Kind() // ptr or not?
if k != reflect.Ptr {
return json.Marshal(v)
}
// dereference pointer
v2 := reflect.ValueOf(v).Elem().Interface()
return MyJSONMarshal(v2)
}
YMMV用这个方法。
是否可以忽略结构的自定义 MarshalJSON
实现,
并只使用标准编组函数?
结构复杂,嵌套结构很多,都是
使用自定义 MarshalJSON
,我想忽略它们。
感觉应该是微不足道的。你有什么想法吗?
一些细节
创建新类型的明显解决方案效果不佳,因为嵌套结构仍然使用它们的 MarshalJSON
s。
代码示例如下:
func (de DeploymentExtended) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if de.Location != nil {
objectMap["location"] = de.Location
}
if de.Properties != nil {
objectMap["properties"] = de.Properties
}
if de.Tags != nil {
objectMap["tags"] = de.Tags
}
return json.Marshal(objectMap)
}
还有很多属性(如 Name
等),我希望在我的 JSON 中看到这些属性(Properties
和其他嵌套结构也是如此) .
此代码的 Python 实现提供了该数据,我的软件使用它,我(将代码移植到 Go)也希望能够从我的 Go 程序中导出这些数据。
您可以通过两种方式执行此操作:
- 自定义类型(隐藏
MarshalJSON
方法);或 - 自定义编组器(使用
reflect
在运行时忽略任何MarshalJSON
方法)
自定义类型
例如,采用这些嵌套类型:
type Y struct {
FieldZ string
}
type X struct {
Name string
Y Y
}
func (x *X) MarshalJSON() ([]byte, error) { return []byte(`"DONT WANT THIS"`), nil }
func (y *Y) MarshalJSON() ([]byte, error) { return []byte(`"DEFINITELY DONT WANT THIS"`), nil }
需要隐藏这些类型以避免调用不需要的 MarshalJSON
方法:
type shadowY struct {
FieldZ string
}
type shadowX struct {
Name string
Y shadowY
}
//
// transform original 'x' to use our shadow types
//
x2 := shadowX{
Name: x.Name,
Y: shadowY(x.Y),
}
https://go.dev/play/p/vzKtb0gZZov
反思
这是一个简单的基于 reflect
的 JSON 封送拆收器来实现您想要的。它假定所有自定义编组器都使用指针接收器 - 并取消引用指针,因此标准库的 json.Marshal
不会“看到”它们:
func MyJSONMarshal(v interface{}) (bs []byte, err error) {
k := reflect.TypeOf(v).Kind() // ptr or not?
if k != reflect.Ptr {
return json.Marshal(v)
}
// dereference pointer
v2 := reflect.ValueOf(v).Elem().Interface()
return MyJSONMarshal(v2)
}
YMMV用这个方法。