Golang序列化/反序列化空数组不是null

时间:2015-10-17 05:21:52

标签: json rest serialization go deserialization

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

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

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

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

3 个答案:

答案 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响应层中添加解决问题的代码。对库的更改很小,并且可以随时发布。