简单谈一些 JSON 数据处理的小知识。近期工作中,因为要把数据库数据实时更新到 elasticsearch,在实践过程中遇到了一些 JSON 数据处理的问题。

实时数据

实时数据获取是通过阿里开源的 canal 组件实现的,并传通过消息队列 kafka 传输给处理程序。我们将接收到的 JSON 数据类似如下的形式。

{"type": "UPDATE","database": "blog","table": "blog","data": [{"blogId": "100001","title": "title","content": "this is a blog","uid": "1000012","state": "1"}]
}

简单说下数据的逻辑,type 表示数据库事件是新增、更新还是删除事件,database 表示对应的数据库名称,table 表示相应的表名称,data 即为数据库中数据。

怎么处理这串 JSON 呢?

json 转化为 map

最先想到的方式就是通过 json.Unmarshal 将 JSON 转化 map[string]interface{}。

示例代码:

func main () {msg := []byte(`{"type": "UPDATE","database": "blog","table": "blog","data": [{"blogId": "100001","title": "title","content": "this is a blog","uid": "1000012","state": "1"}]}`)var event map[string]interface{}if err := json.Unmarshal(msg, &event); err != nil {panic(err)}fmt.Println(event)
}

打印结果如下:

map[data:[map[title:title content:this is a blog uid:1000012 state:1 blogId:100001]] type:UPDATE database:blog table:blog]

到此,就成功解析出了数据。接下来是使用它,但我觉得 map 通常有几个不足。

  • 通过 key 获取数据,可能出现不存在的 key,为了严谨,需要检查 key 是否存在;
  • 相对于结构体的方式,map数据提取不便且不能利用 IDE 补全检查,key 容易写错;

针对这个情况,可以怎么处理呢?如果能把 JSON 转化为struct 就好了。

json 转化为 struct

在 GO 中,json 转化为 struct 也非常方便,只需提前定义好转化的 struct 即可。我们先来定义一下转化的 struct。

type Event struct {Type     string              `json:"type"`Database string              `json:"database"`Table    string              `json:"table"`Data     []map[string]string `json:"data"`
}

说明几点

  • 实际场景中,canal 消息的 data 结构是由表决定的,在 JSON 成功解析前无法提前知道,所以这里定义为 map[string]string;
  • 转化的结构体成员必须是可导出的,所以成员变量名都是大写,而与 JSON 的映射通过 json:"tagName" 的 tagName 完成。

解析代码非常简单,如下:

e := Event{}
if err := json.Unmarshal(msg, &e); err != nil {panic(err)
}fmt.Println(e)

打印结果:

{UPDATE blog blog [map[blogId:100001 title:title content:this is a blog uid:1000012 state:1]]}

接下来,数据的使用就方便了不少,比如事件类型获取,通过 event.Type 即可完成。不过,要泼盆冷水,因为 data 还是 []map[string]string 类型,在使用时,依然存在前面提到的 map 的问题。

能不能把 map 转化为 struct ?

map 转化为 struct

据我所知,map 转化为 struct 的功能,GO 是没有内置的。如果要实现,需要依赖于 GO 的反射机制。

不过,幸运的是,其实已经有人做了这件事,包名称为 mapstructure,使用也非常简单,敲一遍它提供的几个例子就学会了。README 中也说了,该库主要是遇到必须读取一部分 JSON 才能知道剩余数据结构的场景,和我的场景如此契合。

安装命令如下:

$ go get https://github.com/mitchellh/mapstructure

开始使用前,先定义 map 将转化的 struct 结构,即 blog 结构体,如下:

type Blog struct {BlogId  string `mapstructure:"blogId"`Title   string `mapstructrue:"title"`Content string `mapstructure:"content"`Uid     string `mapstructure:"uid"`State   string `mapstructure:"state"`
}

因为,接下来要用的是 mapstructure 包,所以 struct tag 标识不再是 json,而是 mapstructure。

示例代码如下:

e := Event{}
if err := json.Unmarshal(msg, &e); err != nil {panic(err)
}if e.Table == "blog" {var blogs []Blogif err := mapstructure.Decode(e.Data, &blogs); err != nil {panic(err)}fmt.Println(blogs)
}

event 的解析和前面的一样,通过 e.Table 判断是是否来自 blog 表的数据,如果是,使用 Blog 结构体解析。接下来通过 mapstructure 的 Decode 完成解析。

打印结果如下:

[{100001 title this is a blog 1000012 1}]

到此,似乎已经完成了所有工作。非也!

弱类型解析

不知道大家有没有发现一个问题,那就是 Blog 结构体中的所有成员都是 string,这应该是 canal 做的事情,所有的值类型都是 string。但实际上 blog 表中的 uid 和 state 字段其实都是 int。

理想的结构体定义应该是下面这样。

type Blog struct {BlogId  string `mapstructure:"blogId"`Title   string `mapstructrue:"title"`Content string `mapstructure:"content"`Uid     int32  `mapstructure:"uid"`State   int32  `mapstructure:"state"`
}

但是当把新的 Blog 类型代入之前的代码,会报如下错误。

panic: 2 error(s) decoding:* '[0].state' expected type 'int32', got unconvertible type 'string'
* '[0].uid' expected type 'int32', got unconvertible type 'string'

提示类型解析失败。其实,这种形式的 json 在其他一些弱类型语言中也会出现。

那如何解决这个问题?提两种解决方案

  • 使用时进行转化,比如类型为 int 的数据,使用时可以用 strconv.Atoi 转化。
  • 使用 mapstructure 提供的软类型 map 转化 struct 的功能;

显然,第一种方式太 low,转化的时候还要多一步错误检查。那第二种方式如何呢?

来看示例代码,如下:

var blogs []Blog
if err := mapstructure.WeakDecode(e.Data, &blogs); err != nil {panic(err)
}fmt.Println(blogs)

其实只需要把 mapstructure 的 Decode 替换成 WeakDecode 就行了,字如其意,若解析。如此easy。

到此,才算完成!接下来的数据处理就简单很多了。如果想学习 mapstructure 的使用,敲敲源码中例子应该差不多了。

flask json传输失败_GO小知识之实例演示 json 如何转化为 map 和 struct相关推荐

  1. json string 格式_GO小知识之如何做JSON美化

    经常有些小知识想分享出来,但又构不成体系,一直觉得文章形式发出不太合适.准备以 "知乎想法" 分享出来,但发现代码展示不太友好.还是发文章吧,该类分享将以 "小知识&qu ...

  2. GO小知识之实例演示 json 如何转化为 map 和 struct

    今天简单谈一些 JSON 数据处理的小知识.近期工作中,因为要把数据库数据实时更新到 elasticsearch,在实践过程中遇到了一些 JSON 数据处理的问题. 实时数据 实时数据获取是通过阿里开 ...

  3. golang常用库之mapstructure包 | 多json格式情况解析、GO json 如何转化为 map 和 struct、Go语言结构体标签(Struct Tag)

    文章目录 golang常用库之mitchellh/mapstructure包 | go将map转换为struct 一.msgpack 二.背景 三.多json格式情况解析使用思路 四.mapstruc ...

  4. GO小知识之如何做JSON美化

    后端http接口测试常需要打印 JSON 返回,但是默认的json展示形式是紧凑型的,不易阅读,或许很多人习惯于使用在线格式化工具.但如果能用代码直接 JSON 美化,为什么还要多开一次浏览器呢? s ...

  5. flask中的CBV , flask-session在redis中存储session , WTForms数据验证 , 偏函数 , 对象里的一些小知识...

    flask中的CBV , flask-session在redis中存储session , WTForms数据验证 , 偏函数 , 对象里的一些小知识 flask中的CBV写法 后端代码 # 导入vie ...

  6. vue hot true 不起作用_Vue + Flask 小知识(二)

    微信公众号:萝卜大杂烩 关注可了解更多的原创内容.问题或建议,请公众号留言或加本人微信;如果你觉得文章对你有帮助,欢迎加微信交流 今天继续分享 Vue.js 学习笔记,结合 handsontable. ...

  7. 微信小程序打开项目提示读取project.config.json文件失败

    前几天一个月薪35k的兄弟,给我推了一个人工智能学习网站,看了一段时间挺有意思的.包括语音识别.机器翻译等从基础到实战都有,很详细,分享给大家.大家及时保存,说不定啥时候就没了. 微信小程序打开项目提 ...

  8. JS小知识,如何将 CSV 转换为 JSON 字符串

    大家好,今天和大家聊一聊,在前端开发中,我们如何将 CSV 格式的内容转换成 JSON 字符串,这个需求在我们处理数据的业务需求中十分常见,你是如何处理的呢,如果你有更好的方法欢迎在评论区补充. 一. ...

  9. 蓝牙Bluetooth技术小知识

    蓝牙Bluetooth技术以及广泛的应用于各种设备,并将继续在物联网IoT领域担任重要角色.下面搜集整理了一些关于蓝牙技术的小知识,以备参考. 蓝牙Bluetooth技术始创于1994年,其名字来源于 ...

最新文章

  1. UVa1153 Keep The Customer Satisfied(贪心)
  2. Python中斐波那契数列的四种写法
  3. 【MM模块】RFQ 采购询价单
  4. webplugin 没有画面_[问题记录] webpack devServer HtmlWebpackPlugin 没有加载 js、css
  5. js获取php单选按钮值,js如何获取radio单选框选中的值
  6. scala集合中添加元素_如何在Scala中将元素添加到列表中?
  7. 服务器怎么做虚拟空间,服务器怎么做虚拟空间
  8. vue computed使用_前端发展方向指南—Vue运行机制
  9. 26种土的掉渣的东西,看你有多少
  10. android 蓝牙播放器,Android 蓝牙音乐播放器
  11. Unable to launch WebDriverAgent because of xcodebuild failure: “iproxy exited with code ‘234‘“
  12. Clipboard.js实现复制文本到剪贴板功能
  13. Java——反射(reflection)详解
  14. canvas实现漂亮的下雨效果
  15. unity3D用什么语言开发好?
  16. 区块链时代的大数据生态
  17. alias自定义快捷键及去掉“overwrite”提示的方法
  18. Styled-Components
  19. 2021-11-15 基于音乐商店NetMusicShop的复杂查询(二)
  20. 基于BiLSTM的回归预测方法

热门文章

  1. Java常用api和操作必背
  2. 13_新闻客户端界面搭建
  3. (转)深入理解Java的接口和抽象类
  4. Python 如何在csv中定位非数字和字母的符号
  5. windows bat 设置代理上网脚本bat
  6. 读书笔记--疯狂Android讲义 目录
  7. .NET (C#)ASP.NET 应用程序与页面生命周期
  8. 安装Android开发工具
  9. Cacti 监控平台搭建
  10. Linux进程管理工具 Supervisor详解