gpt4 book ai didi

json - 解码 JSON 保留空值

转载 作者:行者123 更新时间:2023-12-01 22:26:18 27 4
gpt4 key购买 nike

我的情况如下:

我有一个用 Go 制作的服务器/ worker 。在后台例程中,服务器接收 JSON 格式的消息,然后使用此数据更新 MongoDB 数据库。

问题之一是,某些 MongoDB 数据类型(例如 ObjectId 和 Date)在必须表示为 JSON 时通常会转换为字符串,因此在将该数据插入数据库之前,我会在结构中解码该 JSON,然后然后将该结构发送到 MongoDB 驱动程序。该结构体实现了诸如 UnmarshalJSON 等方法。和 MarshalBSONValue ,因此它们的数据类型被保留。

太好了,一切都解决了。但是通过使用结构,我遇到了另一个问题,假设我有以下结构:

type Integers struct {
Foo *int `json:"foo" bson:"foo"`
Bar *int `json:"bar" bson:"foo"`
Baz *int `json:"baz" bson:"foo"`
}

然后我收到以下 JSON:
{"foo": 0, "bar": null}

有了这个 JSON,我应该用 foo = 0 更新我的数据库, bar = null ,并忽略 baz .但是,如果我在我的结构中解码这个 JSON,我将有等价物:
Integers{
Foo: 1,
Bar: nil,
Baz: nil,
}

但是我不知道我是否收到了 barbaz ,或者他们只是默认为 nil ,所以我无法正确更新数据库。

我如何相信它可以解决:

通过具有以下结构:
type Integers struct {
Foo SmartassInt `json:"foo,omitempty" bson:"foo,omitempty"`
Bar SmartassInt `json:"bar,omitempty" bson:"bar,omitempty"`
Baz SmartassInt `json:"baz,omitempty" bson:"baz,omitempty"`
}

我将能够区分 null ,以及一个未接收到的值,如下例所示:
var foo int = 0
var fooPointer *int = &foo
var barPointer *int = nil

integers := Integers{
Foo: &fooPointer,
Bar: &barPointer,
Baz: nil,
}

采用这种结构, baz不会被插入到数据库中,因为它的值为 nil , 和 nil由于标志 omitempty 被忽略. bar然而不是 nil ,但它指向 nil ,这与空不同,因此正确插入为 null在数据库中。

但是如何使用接收到的 JSON 实现此初始化?

标准的 JSON 解码器会同时初始化 barbaznil .

实现我自己的编码方法,例如
type NullableInt **int

func (i NullableInt) MarshalJSON() ([]byte, error) {

}

func (i NullableInt) UnmarshalJSON(data []byte) error {

}

也不可能,因为 NullableInt是一个指针,我不能在指针上实现方法。

那么,我可以使用哪种方法来解决这个问题?

最佳答案

在解码端,您可以为自定义类型编写自定义解码器:

type MaybeInt struct {
Present bool
Null bool
Value int64
}

func (m *MaybeInt) UnmarshalJSON(data []byte) error {
s := string(data)
m.Present = true
if s == "null" {
m.Null = true
return nil
}
v, err := strconv.ParseInt(s, 10, 64)
m.Value = v
return err
}

完整示例 here .不幸的是,这在编码端不起作用: MarshalJSON 没有办法。处理程序以指示该字段为空。显而易见的方法是返回 nil, nil来自 Marshaler,但这不起作用。也不会返回 []byte{}, nil .

您可能会想:好吧,让我们使用一个指针,并将其设置为 nil当我们想说应该省略该字段时。这适用于解码端,但现在编码端失败,因为编码器看到文字 null并且根本不调用我们的编码器!

最终,我们可以结合这两种技术:读入 MaybeInt , 编码(写入)来自 *MaybeInt .我们需要并行结构类型。我们可以根据输入类型设置输出类型。我不认为这很漂亮,而且 reflect其中的代码很糟糕(你也可以看到我所有的调试跟踪),但这实际上似乎有效: Playground link .在实践中,而不是使用 reflect ,您可能只为每个“可能”值的情况编写一个函数。

关于json - 解码 JSON 保留空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59797143/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com