为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
小唯快跑啊 2021-11-15 16:59:49
有没有办法序列化结构的空数组属性(非空)并将其反序列化回空数组(再次不是空)?考虑到空数组实际上是指向 null 的指针,在序列化/反序列化之后,空数组和指向 null 的指针之间可感知的初始差异是否完全丢失?最糟糕的实际情况是,当我第一次向我的 REST 客户端显示一个空数组属性时,作为 json "att":[],并且在缓存注册到 redis 并恢复它之后,相同的属性显示给我的客户端为“att”:null,导致合同破裂和很多混乱。总结:在序列化/反序列化 => https://play.golang.org/p/TVwvTWDyHZ之后,可以像 json 空数组一样显示 Customer 2 地址
查看完整描述

3 回答

?
DIEA

TA贡献1820条经验 获得超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 指出的那样,这里的限制是 if在编码之前Addresses真的是nil,一旦解码,您将不会获得 json 等效项null,而是最终得到一个空列表。


查看完整回答
反对 回复 2021-11-15
?
米脂

TA贡献1836条经验 获得超3个赞

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

如果两个数组类型具有相同的元素类型和相同的数组长度,则它们是相同的。

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

nil slice、map 或 channel 的长度为 0

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

如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零。

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

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


查看完整回答
反对 回复 2021-11-15
?
三国纷争

TA贡献1804条经验 获得超7个赞

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


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 466 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信