有没有办法序列化结构的空数组属性(非空)并将其反序列化为空数组(不再为null)?
考虑到一个空数组实际上是一个指向null的指针,在序列化/反序列化之后,空数组和指向null的指针之间的可感知的初始差异是否完全丢失?
最糟糕的实际情况是,当我向我的REST客户端显示一个空数组属性时,作为json“att”:[],在第一次,并且,在缓存注册到redis并恢复之后,相同的属性是我的客户端显示为“att”:null,导致合同中断并且很多令人困惑。
总结:在序列化/反序列化=>之后,可以显示客户2地址,如json空数组。 https://play.golang.org/p/TVwvTWDyHZ
答案 0 :(得分:11)
我很确定你能做到的最简单的方法就是改变你的行
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
,而是最终得到一个空列表。
答案 1 :(得分:6)
不,这是不可能的。为了理解原因,让我们来看看Go规范。为了输出空的与nil的两个不同的结果,任何序列化方法都需要能够分辨出两者之间的区别。但是,根据Go规范,
如果两个数组类型具有相同的元素类型,则它们是相同的 相同的数组长度。
由于既不包含任何元素也没有相同的元素类型,唯一的区别可能是长度,但它也表明
零片,地图或通道的长度为0
通过比较,它无法分辨。当然,除了比较之外还有其他方法,所以要真正把钉子钉在棺材里,这里的部分显示它们具有相同的底层表示。该规范也保证了
如果结构或数组类型不包含任何字段(或 元素,分别),大小大于零。
所以零长度数组的实际分配结构必须为零。如果它的大小为零,则无法存储有关它是否为空或nil
的任何信息,因此对象本身也无法知道。简而言之,nil
数组和零长度数组之间没有区别。
在序列化/反序列化过程中,“空数组和指向null的指针之间可感知的初始差异”不会丢失,从初始分配完成时就会丢失。
答案 2 :(得分:0)
对于另一个解决方案,我们有forked encoding/json添加了一个名为MarshalSafeCollections()
的新方法。此方法将将Slices / Arrays / Maps封送为它们各自的空值([]
/ {}
)。由于大多数实例化都发生在数据层,因此我们不想在http响应层中添加解决问题的代码。对库的更改很小,并且可以随时发布。