Nig*_*hee 12 null json struct go
在golang中,有没有办法看看我是否可以区分json字段被设置为null而json字段在没有编组到结构中时不存在?因为两者都将结构中的值设置为nil,但是我需要知道该字段是否在那里开始并查看是否有人将其设置为null.
{
"somefield1":"somevalue1",
"somefield2":null
}
Run Code Online (Sandbox Code Playgroud)
VS
{
"somefield1":"somevalue1",
}
Run Code Online (Sandbox Code Playgroud)
当编组成结构时,两个jsons都将为nil.任何有用的资源将非常感谢!
Sos*_*doc 16
如果您使用的是 Go 1.18+,您可以使用一个简单的通用结构来了解 JSON 值何时为undefinedor null:
type Optional[T any] struct {
Defined bool
Value *T
}
// UnmarshalJSON is implemented by deferring to the wrapped type (T).
// It will be called only if the value is defined in the JSON payload.
func (o *Optional[T]) UnmarshalJSON(data []byte) error {
o.Defined = true
return json.Unmarshal(data, &o.Value)
}
Run Code Online (Sandbox Code Playgroud)
就这样,您可以在结构中使用这种类型:
type Payload struct {
Field1 Optional[string] `json:"field1"`
Field2 Optional[bool] `json:"field2"`
Field3 Optional[int32] `json:"field3"`
}
Run Code Online (Sandbox Code Playgroud)
您将能够使用该Defined字段来了解该字段是否是null或undefined。
检查此游乐场链接以获取完整示例: https: //go.dev/play/p/JZfZyVVUABz
另一种方法是使用自定义类型:
// OptionalString is a struct that represents a JSON string that can be
// undefined (Defined == false), null (Value == nil && Defined == true) or
// defined with a string value
type OptionalString struct {
Defined bool
Value *string
}
// UnmarshalJSON implements the json.Unmarshaler interface.
// When called, it means that the value is defined in the JSON payload.
func (os *OptionalString) UnmarshalJSON(data []byte) error {
// UnmarshalJSON is called only if the key is present
os.Defined = true
return json.Unmarshal(data, &os.Value)
}
// Payload represents the JSON payload that you want to represent.
type Payload struct {
SomeField1 string `json:"somefield1"`
SomeField2 OptionalString `json:"somefield2"`
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用常规json.Unmarshal函数来获取您的值,例如:
var p Payload
_ = json.Unmarshal([]byte(`{
"somefield1":"somevalue1",
"somefield2":null
}`), &p)
fmt.Printf("Should be defined == true and value == nil: \n%+v\n\n", p)
p = Payload{}
_ = json.Unmarshal([]byte(`{"somefield1":"somevalue1"}`), &p)
fmt.Printf("Should be defined == false \n%+v\n\n", p)
p = Payload{}
_ = json.Unmarshal([]byte(`{
"somefield1":"somevalue1",
"somefield2":"somevalue2"
}`), &p)
fmt.Printf("Parsed should be defined == true and value != nil \n%+v\n", p)
if p.SomeField2.Value != nil {
fmt.Printf("SomeField2's value is %s", *p.SomeField2.Value)
}
Run Code Online (Sandbox Code Playgroud)
应该给你这个输出:
Should be defined == true and value == nil:
{SomeField1:somevalue1 SomeField2:{Defined:true Value:<nil>}}
Should be defined == false
{SomeField1:somevalue1 SomeField2:{Defined:false Value:<nil>}}
Parsed should be defined == true and value != nil
{SomeField1:somevalue1 SomeField2:{Defined:true Value:0xc000010370}}
SomeField2's value is somevalue2
Run Code Online (Sandbox Code Playgroud)
链接到包含完整示例的游乐场:https ://play.golang.org/p/AUDwPKHBs62
请注意,对于要包装的每种类型,您都需要一个结构体,因此,如果您需要可选数字,则需要创建一个OptionalFloat64具有类似实现的结构体(所有 JSON 数字都可以是 64 位浮点数)。如果/当泛型登陆 Go 时,这可以简化为单个泛型结构。
Pie*_*Pah 10
使用json.RawMessage以"拖延"解组过程决定做某件事之前要确定原始字节:
var data = []byte(`{
"somefield1":"somevalue1",
"somefield2": null
}`)
type Data struct {
SomeField1 string
SomeField2 json.RawMessage
}
func main() {
d := &Data{}
_ = json.Unmarshal(data, &d)
fmt.Println(d.SomeField1)
if len(d.SomeField2) > 0 {
if string(d.SomeField2) == "null" {
fmt.Println("somefield2 is there but null")
} else {
fmt.Println("somefield2 is there and not null")
// Do something with the data
}
} else {
fmt.Println("somefield2 doesn't exist")
}
}
Run Code Online (Sandbox Code Playgroud)
查看游乐场https://play.golang.org/p/Wganpf4sbO
如果您将对象解组到 map[string]interface{} 中,那么您只需检查字段是否存在
type unMarshalledObject map[string]interface{}
json.Unmarshal(input, unMarshalledObject)
_, ok := unMarshalledObject["somefield2"]
Run Code Online (Sandbox Code Playgroud)
好问题。
我相信您可以将https://golang.org/pkg/encoding/json/#RawMessage用作:
type MyMessage struct {
somefield1 string
somefield2 json.RawMessage
}
Run Code Online (Sandbox Code Playgroud)
因此,解组后,你应该[]byte("null")在的情况下,null和nil如果它丢失了。
这是一个操场代码:https : //play.golang.org/p/UW8L68K068