【问题标题】:Golang serialize/deserialize an Empty Array not as nullGolang 序列化/反序列化一个空数组而不是 null
【发布时间】:2016-01-15 22:47:50
【问题描述】:

有没有办法序列化结构的空数组属性(非空)并将其反序列化回空数组(再次非空)?

考虑到空数组实际上是指向null的指针,在序列化/反序列化之后,空数组和指向null的指针之间的可感知初始差异是否完全丢失?

最糟糕的实际情况是,当我第一次向我的 REST 客户端显示一个空数组属性时,作为 json "att":[],并且在缓存注册到 redis 并恢复它之后,相同的属性是向我的客户显示为“att”:null,导致合同破裂并且造成很多混乱。

总结:在序列化/反序列化之后可以像json空数组一样显示客户2地址=> https://play.golang.org/p/TVwvTWDyHZ

【问题讨论】:

标签: json rest serialization go deserialization


【解决方案1】:

不,这是不可能的。要了解原因,让我们看一下 Go 规范。为了输出空和零的两个不同结果,任何序列化方法都需要能够区分两者之间的区别。但是,根据 Go 规范,

如果两个数组类型具有相同的元素类型并且 相同的数组长度。

由于两者都不包含任何元素并且具有相同的元素类型,唯一的区别可能是长度,但它也指出

nil slice、map 或 channel 的长度为 0

所以通过比较,它无法分辨。当然,除了比较之外,还有其他方法,所以要真正把钉子钉在棺材里,这里是显示它们具有相同底层表示的部分。该规范还保证

如果结构或数组类型不包含任何字段(或 元素,分别)具有大于零的大小。

所以实际分配的零长度数组结构的大小必须为零。如果它的大小为零,它就不能存储关于它是空的还是nil 的任何信息,所以对象本身也不知道。简而言之,nil 数组和零长度数组没有区别。

在序列化/反序列化过程中,“空数组和指向 null 的指针之间可感知的初始差异”不会丢失,它从初始分配完成的那一刻起就丢失了。

【讨论】:

  • 向上,因为这实际上是它的工作原理。请参阅我的回答中的@mike 评论以了解我的解决方案的局限性。
  • 使用指向切片的指针怎么样?就像你会做一个指向字符串的指针,所以它可以是零?这可能吗?
  • 你仍然可以分辨出来,因为你可以和nil进行比较:play.golang.org/p/fxV0atFXJSX
【解决方案2】:

我很确定你能做到的最简单的方法就是改变你的线路

var cust1_recovered Customer

cust1_recovered := Customer{Addresses: []Address{}}

除非我读错了你的问题,否则我相信这是你想要的输出:

ORIGINAL  Customer 2 {
  "Name": "Customer number 2",
  "Addresses": []
}
RECOVERED Customer 2 {
  "Name": "Customer number 2",
  "Addresses": []
}

这是一个验证的游乐场:https://play.golang.org/p/T9K1VSTAM0

这里的限制,正如@mike 所指出的,如果Addresses 在你编码之前真的是nil,一旦你解码你就不会得到 json 等效的null,而是会以一个空列表结束.

【讨论】:

  • 不知道为什么这被否决了。它执行 OP 的要求,返回一个空的 json 数组来代替 null。
  • 不是反对者,但我会假设因为它实际上并没有区分两者。如果原来是nil,现在应该是[]
  • @MikePrecup:除非我读错了 OP 的问题,否则我相信这就是他们所追求的。
  • Arf,我的错,我误解了你的回答并且投票太快了,对不起。它现在已锁定,但如果您可以编辑您的答案(例如添加游乐场链接),我将能够将其更改为赞成票。编辑:好的,赞成
  • @MikePrecup,我明白你的意思。我想这取决于 OP,也可能取决于系统是否可以使用 nil Addresses。根据关于“导致合同破裂”的评论,我认为空数组总是需要的。
【解决方案3】:

对于另一种解决方案,我们有forked encoding/json 添加一个名为MarshalSafeCollections() 的新方法。此方法将 Slices/Arrays/Maps 编组为它们各自的空值 ([]/{})。由于我们的大部分实例化都发生在数据层上,我们不想在我们的 http 响应层中添加修复问题的代码。对库的更改很少,并遵循 go 版本。

【讨论】:

    猜你喜欢
    • 2013-04-17
    • 2012-08-10
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 2021-11-29
    相关资源
    最近更新 更多