猿问

Golang 序列化/反序列化一个不为 null 的空数组

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

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

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

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


小唯快跑啊
浏览 467回答 3
3回答

DIEA

我很确定你能做到的最简单的方法就是改变你的线路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 指出的那样,这里的限制是 if在编码之前Addresses真的是nil,一旦解码,您将不会获得 json 等效项null,而是最终得到一个空列表。

米脂

不,这不可能。要了解原因,让我们看看 Go 规范。为了输出空与零的两个不同结果,任何序列化方法都需要能够区分两者之间的区别。但是,根据 Go 规范,如果两个数组类型具有相同的元素类型和相同的数组长度,则它们是相同的。由于两者都不包含任何元素并且具有相同的元素类型,唯一的区别可能是长度,但它也指出nil slice、map 或 channel 的长度为 0所以比较起来,就分不清了。当然,除了比较还有其他方法,所以要真正把钉子钉在棺材里,这里是显示它们具有相同底层表示的部分。该规范还保证如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零。所以零长度数组的实际分配结构的大小必须为零。如果它的大小为零,则它无法存储有关它是空的还是 的任何信息nil,因此对象本身也无法知道。简而言之,nil数组和零长度数组之间没有区别。在序列化/反序列化过程中不会丢失“空数组和指向 null 的指针之间的可感知初始差异”,它从初始分配完成的那一刻起就丢失了。

三国纷争

对于另一个解决方案,我们分叉了 encoding/json以添加一个名为MarshalSafeCollections(). 此方法将 Slices/Arrays/Maps 编组为它们各自的空值 ( []/ {})。由于我们的大部分实例化发生在数据层,我们不想在 http 响应层添加修复问题的代码。对库的更改很小,并遵循 go 版本。
随时随地看视频慕课网APP

相关分类

Go
我要回答