文章插图
Go 语言是静态类型语言,虽然它也可以表现出动态类型,但是使用一个嵌套的 map[string]interface{} 在那里乱叫会让代码变得特别丑 。通过掌握语言的静态特性,我们可以做的更好 。
通过同一通道交换多种信息的时候,我们经常需要 JSON 具有动态的,或者更合适的参数内容 。首先,让我们来讨论一下消息封装(message envelopes),JSON 在这里看起来就像这样:
{ "type": "this part tells you how to interpret the message", "msg": ...the actual message is here, in some kind of json...}通过不同的消息类型生成 JSON通过 interface{},我们可以很容易的将数据结构编码成为独立封装的,具有多种类型的消息体的 JSON 数据 。为了生成下面的 JSON :
{ "type": "sound", "msg": { "description": "dynamite", "authority": "the Bruce Dickinson" }}{ "type": "cowbell", "msg": { "more": true }}我们可以使用这些 Go 类型:
文章插图
输出的结果是:
{"Type":"sound","Msg":{"Description":"dynamite","Authority":"the Bruce Dickinson"}}{"Type":"cowbell","Msg":{"More":true}}这些并没有什么特殊的 。
解析 JSON 到动态类型如果你想将上面的 JSON 对象解析成为一个 Envelope 类型的对象,最终你会将 Msg 字段解析成为一个 map[string]interface{} 。这种方式不是很好用,会使你后悔你的选择 。
文章插图
输出:
dynamite明确的解析方式就像前面说的,我推荐修改 Envelope 类型,就像这样:
type Envelope { Type string Msg *json.RawMessage}json.RawMessage 非常有用,它可以让你延迟解析相应的 JSON 数据 。它会将未处理的数据存储为 []byte 。
这种方式可以让你显式控制 Msg 的解析 。从而延迟到获取到 Type 的值之后,依据 Type 的值进行解析 。这种方式不好的地方在于你需要先明确解析 Msg,或者你需要单独分为 EnvelopeIn 和 EnvelopeOut 两种类型,其中 EnvelopeOut 仍然有 Msg interface{} 。
结合 *json.RawMessage 和 interface{} 的优点那么如何将上述两者好的一面结合起来呢?通过在 interface{} 字段中放入 *json.RawMessage!
文章插图
输出:
dynamite如何把所有数据都放在最外层(顶层)虽然我极其推荐你将动态可变的部分放在一个单独的 key 下面,但是有时你可能需要处理一些预先存在的数据,它们并没有用这样的方式进行格式化 。
如果可以的话,请使用文章前面提到的风格 。
{ "type": "this part tells you how to interpret the message", ...the actual message is here, as multiple keys...}我们可以通过解析两次数据的方式来解决 。
文章插图
【Go 语言中的动态 JSON】dynamite
推荐阅读
- 每个C语言程序员都应该明白,计算机究竟是如何存储小数的?
- C语言5种必须要搞懂的常量
- 漫话凤冈方言中的茶风之五
- 漫话凤冈方言中的茶风(之四
- 漫话凤冈方言中的茶风之七
- 刷天猫店铺动态评分 天猫动态评分快速提高
- 西伯利亚冻土层有多少猛犸象 冻土中的猛犸象
- 白茶中的学问 不懂的快看看
- 我用北京工作居住证,办成了人生中的4件大事,你也可以哦
- 减肥中,主食怎么吃才不会胖?