热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

flaskjson传输失败_GO小知识之实例演示json如何转化为map和struct

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

83fde7e3fc203fcc99814de952c9d9c2.png

简单谈一些 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 的使用,敲敲源码中例子应该差不多了。



推荐阅读
  • 在Elasticsearch中,映射(mappings)定义了索引中字段的结构,类似于传统数据库中的表结构。虽然Elasticsearch支持字段的增删,但直接修改字段类型是不允许的。本文介绍了一种通过创建新索引并迁移数据的方式来改变字段类型的方法。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 离线安装Grafana Cloudera Manager插件并监控CDH集群
    本文详细介绍如何离线安装Cloudera Manager (CM) 插件,并通过Grafana监控CDH集群的健康状况和资源使用情况。该插件利用CM提供的API接口进行数据获取和展示。 ... [详细]
  • docker镜像重启_docker怎么启动镜像dock ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 本文介绍如何使用MFC和ADO技术调用SQL Server中的存储过程,以查询指定小区在特定时间段内的通话统计数据。通过用户界面选择小区ID、开始时间和结束时间,系统将计算并展示小时级的通话量、拥塞率及半速率通话比例。 ... [详细]
  • 简化报表生成:EasyReport工具的全面解析
    本文详细介绍了EasyReport,一个易于使用的开源Web报表工具。该工具支持Hadoop、HBase及多种关系型数据库,能够将SQL查询结果转换为HTML表格,并提供Excel导出、图表显示和表头冻结等功能。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 58同城的Elasticsearch应用与平台构建实践
    本文由58同城高级架构师于伯伟分享,由陈树昌编辑整理,内容源自DataFunTalk。文章探讨了Elasticsearch作为分布式搜索和分析引擎的应用,特别是在58同城的实施案例,包括集群优化、典型应用实例及自动化平台建设等方面。 ... [详细]
  • 在CentOS 7上轻松安装Elasticsearch的JDBC插件
    本文介绍如何在CentOS 7操作系统中安装Elasticsearch (简称ES) 的JDBC插件,以实现与MySQL数据库的有效连接,特别强调了该方法对于增量数据同步的支持。 ... [详细]
author-avatar
hhxsv5
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有