一 datatypes.JSON
- 这个类型可以直接在模型中定义, 与 mysql数据库中的 json类型适配。 可以采用gorm的方法,实现json数据的存储。
二 json.RawMessage
-
第一点用法可以参照这篇文章:https://xiuxiuing.blog.csdn.net/article/details/98059950
-
第二点: 这里涉及到一个使用场景:
一个模型数据库表, 这个模型可能是飞机模型,汽车模型等等。 他们可能有公共字段,比如型号,生产厂家。 但是其他的一些详细配置参数不是固定的。所以数据库没法建立字段。 所以就直接存一个json进数据库。 但是我操作后,存进去的json和原来的json,里面元素顺序不对了,这样前端再展示的时候,也没顺序了
-
我之前采用的做法就是 数据库字段定义为 datatypes.JSON(gorm)。 想直接把这个json对象存入数据库。 然后采用的gin框架。设置的结构体字段为 interface{}。 然后
1. BindJSON()
接收, 然后再2. json.marshal
,将转换后的结果赋值给 模型(字段类型就是datatypes.JSON) 存入数据库。 但是这样以转化 json对象的字段顺序就变了。 等把数据库存的 json对象返回给前端,遍历的时候里面属性的顺序就变了。- 提出问题:我很疑惑,底层怎么处理的。 我看了下,gin 框架的 BindJSON() 方法,底层也是调用,http 封装好的 request.Body, 然后绑定数据。 我想存的就是 json类型。 难道就不能拿到前端的数据直接存吗?(直接存应该就不会改变了)。 我现在都是用 空接口去 接收 body中的 json数据,再序列化为 json(其实看到 gorm的 json类型就是 []byte), 存入数据库。
- json数据必须转为 go类型,再序列化才能存, 不是多消耗时间和性能吗?
解答
:转为go的结构体,这样可以对传递的json数据格式进行校验,确保了数据的正确性。 但是想上述的场景中是不能定义出具体的结构体的,通过interface来做转化。解答
:下面引出重点josn.RwaMessage- 于是我开始想, 利用 []byte 类型去接收json数据, 那么直接存,就不会乱序了,但是会提示报错,
不能将数据序列化到 []byte 类型的结构当中
。也就是没有提供序列化的方法。 - 官方的json模块, 提供了 json.RwaMessage 方法:
- 下面是具体的方法实现:也很简单的实现。
- 因为具有了这两个方法, 所以用json.RawMessage来代替 空接口类型来接收前端传递的json数据, 此时调试可以发现,获取到的就是传递的原数据,并没有出现乱序!而datatypes.JSON类型的实现,底层其实也是 []byte, 并且就是一个 json.RawMessage类型
- 那么可以直接使用 datatypes.JSON(data), 做类型转换, 此时存入数据库中,就不会出现乱序的情况,存储的是原来的数据。这样就解决了问题。
- 于是我开始想, 利用 []byte 类型去接收json数据, 那么直接存,就不会乱序了,但是会提示报错,
-
(更新)
:上面的datatypes.JSON实际上就是封装的 json.RawMessage。并且同样实现了两个方法,调用的还是 josn.RwaMessage 的方法:
- 所以可以直接全部用 datatypes.JSON来接收 前端传递的json数据。
-
(继续更新)
:今天又尝试写了一个 update更新接口, 全程采用 datatypes.JSON类型,发现从接收到传递给服务,一直顺序都没变,但是最后存入数据库,还是变了,看来这个和json的协议规定有关, json对象就不是有序的。 不过不是没有收获, 使用datatypes.JSON类型直接存json数据到数据库,方便省事。 除非有定义专门的结构体,做序列化和其他操作,不然直接用datatypes.JSON类型存json,方便。