文章目录

  • 一、引言
  • 二、代码
  • 三、测试

一、引言

距离上次写接口已经过去了一周,那次接口之旅让我明白打印日志的重要性,于是我自定义了一个Log注解,用于打印接受的参数和返回的参数:自定义注解+AOP,优雅的打印方法接受和返回的参数内容。

上一次接口交互的数据是xml格式的数据,由于我对于dom4j不太熟悉,所以就按部就班的使用常规的形式进行解析,效果还算如人意。但是这次接口交互的数据是JSON,我依然不熟悉,但是FastJSON、Gson、Jackson它们熟悉呀,高效的API,丝滑般的体验,能够一边摸着鱼,一边完成领导的任务,舒服。

当我看到对应的业务要求时,我有一点小郁闷,具体的返回JSON数据如下图。返回了一堆的数据,然而我只需要一个id。当然用API也行,只要一层一层的往下解析就好了,可我觉得太麻烦,要写一堆无用的代码(自己太懒了,不想写代码)。

我理想的状况就是我传入一个key,调用对应的API能够直接返回我要的value值。

以下废话,可直接看第二节

最开始我想到的是树结构,把JSON字符串修改为一棵树,然后根据层级和对应的key直接获取,但是这有几个问题:

  1. 我不会写树,百度出来也没看太明白(太菜了)
  2. 相同层级的树可能存在key值一样的情况
  3. 树结构下的map值和list数组交叉在一起以后,我找起来也不方便

综上所述,我放弃了。


二、代码

上面的第二点很关键,然后想到上次解析xml格式数据的经验,我需要传入指定的路径,以此来定位对应的节点值,然后一层一层的往下找。并且我可以获取单个节点值(单个value),也有可以获取一整个大的节点(直接转化为list集合或者map),说干就干,代码从哪里开始写呢?

终于在我的辛苦百度下,找到了一个差不多的功能的代码,然后修修改改(我能说是我的了吗?哈哈),成为了下面的代码。

如果想要直接运行下面的代码,你需要引入相关的依赖:fastjson(数据转换)、commons-lang3(判空)、slf4j(日志)。主要是第一个,后面两个可以把代码相关部分注释掉即可。如果想要支持多种数据源的操作,只需要写一个简单的策略模式就能实现。

现在:传入指定的JSON字符串 + 传入想要获取的目标key + 传入目标key的value类型 = 你想要的结果

public class JsonToolsFastJson {private static String jsonStr = "{\"_id\":\"5973782bdb9a930533b05cb2\",\"isActive\":true,\"balance\":\"$1,446.35\",\"age\":32,\"eyeColor\":\"green\",\"name\":\"Logan Keller\",\"gender\":\"male\",\"company\":\"ARTIQ\",\"email\":\"logankeller@artiq.com\",\"phone\":\"+1 (952) 533-2258\",\"friends\":[{\"id\":0,\"name\":\"Colon Salazar\"},{\"id\":1,\"name\":\"French Mcneil\"},{\"id\":2,\"name\":\"Carol Martin\"}],\"mobian\":[{\"id\":0,\"name\":\"Colon Salazar\",\"arr\":[{\"id\":0,\"name\":\"Colon Salazar\"}]}],\"favoriteFruit\":\"banana\"}";private static final Logger logger = LoggerFactory.getLogger(JsonToolsFastJson.class);public static void main(String[] args) throws Exception {//测试通过json获取Object对象JsonToolsFastJson jsonTools = new JsonToolsFastJson();Object str1 = jsonTools.getObjectByJson(jsonStr, "name", TypeEnum.STRING);logger.info("str1:" + str1);Object str3 = jsonTools.getObjectByJson(jsonStr, "friends", TypeEnum.LIST);logger.info("str3:" + str3);Object str4 = jsonTools.getObjectByJson(jsonStr, "mobian.arr", TypeEnum.LIST);logger.info("str4:" + str4);}// 用于记录递归的次数private int i = 0;/*** 复杂嵌套JSON获取Object数据*/public Object getObjectByJson(String jsonStr, String argsPath, TypeEnum argsType) {if (StringUtils.isBlank(argsPath) || argsType == null) {logger.info("必填参数argsPath或argsType不能为空");return null;}Object obj = null;try {Map maps = JSONObject.parseObject(jsonStr);//多层获取if (argsPath.contains(".")) {obj = getObject(maps, argsPath, argsType);} else {//直接获取if (argsType == TypeEnum.STRING) {obj = JSONObject.parseObject(jsonStr).get(argsPath);} else if (argsType == TypeEnum.MAP) {obj = (Map) JSONObject.parseObject(jsonStr).get(argsPath);} else if (argsType == TypeEnum.LIST) {obj = (List) JSONObject.parseObject(jsonStr).get(argsPath);}}} catch (Exception e) {logger.error(e.getMessage());}return obj;}// 递归获取objectprivate Object getObject(Object m, String key, TypeEnum type) {if (m == null) {System.out.println("over...");return null;}// 返回的对象Object o = null;Map mp = null;List ls = null;try {// 第二层只会出现{}或[]//{}对象层级递归遍历解析if (m instanceof Map) {mp = (Map) m;for (Iterator ite = mp.entrySet().iterator(); ite.hasNext(); ) {Map.Entry e = (Map.Entry) ite.next();//  e  : json中的key-value// key : 传入的pathif (i < key.split("\\.").length && e.getKey().equals(key.split("\\.")[i])) {i++;if (e.getValue() instanceof String) {//递归最后一次if (i == key.split("\\.").length) {o = e.getValue();i = 0;return o;}} else if (e.getValue() instanceof Map) {//递归最后一次if (i == key.split("\\.").length) {if (type == TypeEnum.MAP) {o = (Map) e.getValue();i = 0;return o;}} else {o = getObject((Map) e.getValue(), key, type);}return o;} else if (e.getValue() instanceof List) {//递归最后一次if (i == key.split("\\.").length) {if (type == TypeEnum.LIST) {o = (List) e.getValue();i = 0;return o;}} else {o = getObject((List) e.getValue(), key, type);}return o;}}}}//[]数组层级递归遍历解析// 获取[]数据时,只能直接获取所有[]数据if (m instanceof List) {ls = (List) m;for (int i = 0; i < ls.size(); i++) {if (ls.get(i) instanceof Map) {//递归最后一次if (i == key.split("\\.").length) {if (type == TypeEnum.MAP) {o = (Map) ls.get(i);return o;}} else {o = getObject((Map) ls.get(i), key, type);}return o;} else if (ls.get(i) instanceof List) {//递归最后一次if (i == key.split("\\.").length) {if (type == TypeEnum.LIST) {o = (List) ls.get(i);return o;}} else {o = getObject((List) ls.get(i), key, type);}return o;}}}} catch (Exception e) {logger.error(e.getMessage());}return o;}/*** JSON数据解析返回数据类型枚举,我将value归为3类*/public enum TypeEnum {STRING,MAP,LIST;}
}

补充:对于数组类型的数据,我认为在实际工作中很少会出现我只获取第一个或者某一个数组种数据的情况,所以该测试代码中如果想要获取的目标数据是一个数组,那么得到的结果就是一整个数组数据。


三、测试

测试效果图:

name对应的直接是一个string类型的value

friends对应的是list里面嵌套的map

mobian对应的是一个list,就list中的单个元素而言,它又是一个map,map里面的arr参数对应的又是一个list

JSON代码如下:

{"_id": "5973782bdb9a930533b05cb2","isActive": true,"balance": "$1,446.35","age": 32,"eyeColor": "green","name": "Logan Keller","gender": "male","company": "ARTIQ","email": "logankeller@artiq.com","phone": "+1 (952) 533-2258","friends": [{"id": 0,"name": "Colon Salazar"}, {"id": 1,"name": "French Mcneil"}, {"id": 2,"name": "Carol Martin"}],"mobian": [{"id": 0,"name": "Colon Salazar","arr": [{"id": 0,"name": "Colon Salazar"}]}],"favoriteFruit": "banana"
}

我认为该方法可以当作一个工具方法来使用,现在对于层级很深的数据,我也只需要一行就能解决数据的获取问题,而不再需要一层一层的往下嵌套处理。

若干年后,你离职了,上面的方法有bug,你成功的给同事埋了一个雷,同事打开版本控制工具,看到提交人,大骂一声,xxx垃圾玩意儿。

根据key找到JSON字符串中指定的value值(Java实现)相关推荐

  1. Java黑皮书课后题第6章:*6.23(指定字符的出现次数)使用下面的方法头编写一个方法,找到一个字符串中指定字符的出现次数。编写一个测试程序,提示用户输入一个字符串以及一个字符,显示该字符出现次数

    6.23(指定字符的出现次数)使用下面的方法头编写一个方法,找到一个字符串中指定字符的出现次数.编写一个测试程序,提示用户输入一个字符串以及一个字符,显示该字符出现次数 题目 题目描述 破题 代码 运 ...

  2. Newtonsoft中JObject提取Json字符串中某字段的值

    JObject 1.Json是这样的 {title:123,body:456,list:{title:'这是一个标题',body:'what'}} 2.我要将其中几项都搞出来,代码: static v ...

  3. Json格式的字符串修改对应Key的Value值,并保存到原json字符串中

    一.前言 小编今天在工作工程中,遇到了一个处理json字符串的问题,经过半小时的测试,最终解决了此问题!记录一下,为后来人铺路. 小编先说一下需求哈: 我们要把json字符串中的指定key的value ...

  4. json字符串中key值下划线命名转换为驼峰命名

    json字符串中key值下划线命名转换为驼峰命名: 例如: public class JsonUtils {public final static void convert(Object json) ...

  5. JSON字符串转为指定实体类对象

    创建JsonStringToClass对象即可 package utils;import net.sf.json.JSONArray; import net.sf.json.JSONObject;im ...

  6. Jackson第二篇【从JSON字符串中取值】

    来源:http://blog.csdn.net/songyongfeng/article/details/6932674 第一篇咱们主要学习了实体与json的相互转换的问题,但是咱们需要的是数据 你转 ...

  7. php 去掉转义引号的反斜杠,PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠...

    PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠 通过AJAX传到PHP的json字符串有时候加上反斜杠"\"来转义,PHP处理时需要先去掉反斜杠,然后再json_dec ...

  8. java 删除指定字符_字符串删除指定位置字符 JAVA 删除字符串中指定的字符

    <死侍2>有多不按套路出牌? 要CSS布局HTML小编今天和大家分享用到函数的调用. 编制函数fun,其功能是:删除一个字符串中指定的一.问题描述:从键盘输入一个字符串给str和一个字符给 ...

  9. Python接口自动化响应结果json格式化输出+断言响应结果中指定的属性值+其他

    一.Python字典 二.Python元组 三.接口响应值转为字典格式 四.接口响应值以json格式输出并添加到allure报告中 五.断言响应结果中指定的属性值 六.TypeError: strin ...

  10. Excel中如何截取字符串中指定字符后的部分字符

    1.如何给某列属性为时间整体加一个时间值: 场景一:假如我有一个excel中的某一列如下图所示,如何将该列的时间(用B代替整列)整体加一分钟呢?方法很简单,在空白单元格填写时间格式图中A所示:复制单元 ...

最新文章

  1. 自动驾驶外卖上线,美团即将配送一切
  2. C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝
  3. CTFshow 信息收集 web14
  4. 装车机器人_智造春天脚步近 青岛这家机器人公司着手打造模块化、标准化技术平台...
  5. Go 内存对齐的那些事儿
  6. 郑洁又淘汰了一个美女瓦伊迪索娃
  7. php数组转为js json,javascript-将数组php转换为JSON时出错
  8. Java提高篇——equals()方法和“==”运算符
  9. 使用Seam Framework + JBoss 5.0 开发第一个Web应用 - 简单投票程序
  10. Java图像识别车牌_车牌识别测试图片集(237幅车牌照片)(文件名均是车牌号)
  11. 解决PyCharm出现无法连接Docker的问题
  12. Windows下安装 ruby
  13. Paraview源码解析8: vtkPVGlyphFilter类
  14. [OPS][GPU]GPU峰值计算能力计算
  15. ArcGIS许可服务管理器无法启动问题
  16. 《遭遇外星人》读书笔记
  17. JQuery学习——标签页(Tabs)
  18. 搭建区块链浏览器——基于hyperledger fabric 1.0,MySQL容器
  19. HTML中 <img>标签的用法
  20. 周易六十四卦——同人卦

热门文章

  1. android进阶(三)数据存储之Internal Storage
  2. [2018.10.11 T1] 锻造
  3. [2018.10.10 T2] 烯烃
  4. python可视化计算器_Python tkinter实现简单加法计算器代码实例
  5. 计算机学术会议英语作文,计算机专业资料——重要国际学术会议
  6. 关于String的常用方法
  7. android root 技术,android root实践
  8. python 清空文件_python:文件的读取、创建、追加、删除、清空
  9. (13)Spring框架----Spring与Mybatis的框架整合(XML配置详解)
  10. (2)从文件中解析JSON数据