转自:作者:琴水玉
https://www.cnblogs.com/lovesqcc/p/7821641.html

JsonPath:从多层嵌套Json中解析所需要的值
问题
基本方案
JsonPath
小结
问题
应用中,常常要从嵌套的JSON串中解析出所需要的数据。通常的做法是,先将JSON转换成Map, 然后一层层地判空和解析。可使用 JsonPath 来解决这个问题。

给定一个 JSON 串如下所示

{"code":200,"msg":"ok","list":[{"id":20,"no":"1000020","items":[{"name":"n1","price":21,"infos":{"feature":""}}]}],"metainfo":{"total":20,"info":{"owner":"qinshu","parts":[{"count":13,"time":{"start":1230002456,"end":234001234}}]}}}

从中解析出 code, total, count 的值。

基本方案
基本方案就是自己手动将JSON转为Map,然后一层层判空和解析,如下代码所示:

public class JsonUtil {private static final ObjectMapper MAPPER = new ObjectMapper();static {// 为保持对象版本兼容性,忽略未知的属性MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 序列化的时候,跳过null值MAPPER.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);// date类型转化SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");MAPPER.setDateFormat(fmt);}/*** 将一个json字符串解码为java对象** 注意:如果传入的字符串为null,那么返回的对象也为null** @param json json字符串* @param cls  对象类型* @return 解析后的java对象* @throws RuntimeException 若解析json过程中发生了异常*/public static <T> T toObject(String json, Class<T> cls) {if (json == null) {return null;}try {return MAPPER.readValue(json, cls);} catch (Exception e) {return null;}}/*** 读取JSON字符串为MAP*/@SuppressWarnings("unchecked")public static Map<String, Object> readMap(String json) {return toObject(json, HashMap.class);}/*** 对于正确JSON及存在的Path下获取到最终指定值并转成字符串,其他情况一律返回 null* @param json JSON串* @param path 点分隔的字段路径* @return 相应字段的字符串值*/public static String readVal(String json, String path) {if (json == null || path == null) {return null;}Map<String,Object> map = readMap(json);if (map == null) {// log.warn("parse json failed: " + json);return null;}String[] subpaths = path.split("\\.");return readVal(map, subpaths);}private static String readVal(Map<String, Object> map, String path) {return readVal(map, path.split("\\."));}private static String readVal(Map<String, Object> map, String[] subpaths) {Object val = map;try {for (String subpath: subpaths) {if (val != null && val instanceof Map) {val = ((Map)val).get(subpath);}else {// log.warn("subpath may not exists in " + map);return null;}}return val == null ? null: val.toString();} catch (Exception ex) {return null;}}

realVal 的目标就是:对于正常情况下获取到最终指定值并转成字符串,其他情况一律返回 null. readVal 上层函数接受一个JSON串和一个点分割的Path,进行参数校验后交给下层 readVal 函数;下层 readVal 函数对每次取出的值进行判空和取值,如果OK就一直进行到取出最终值;否则要么抛出异常,要么直接返回 null.

对于只需要从嵌套Map中取值的需求,基本是满足了,不过若要从List,Map混合的JSON串中取值,就不够用了。此时,可采用成熟库 JsonPath 来完成这件事。

JsonPath
在网上搜索 jsonpath maven 即可在 mvnrepository 找到 jsonpath 的最新版本。工程中引入

<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency><groupId>com.jayway.jsonpath</groupId><artifactId>json-path</artifactId><version>2.4.0</version>
</dependency>

现在就可以使用JsonPath 了。 基本语法可参考这篇文章: JSONPath基本语法

可以为 JsonPath 包装一层函数, 与现有客户端使用相同。

public static String readValUsingJsonPath(String json, String path) {if (json == null || path == null) {return null;}try {Object val = JsonPath.read(json, "$." + path);return val == null ? null : val.toString();} catch (Exception ex) {return null;}}

编写单测如下:

public class JsonUtilTest extends CommonForTest {String json = "{\"code\":200,\"msg\":\"ok\",\"list\":[{\"id\":20,\"no\":\"1000020\",\"items\":[{\"name\":\"n1\",\"price\":21,\"infos\":{\"feature\":\"\"}}]}],\"metainfo\":{\"total\":20,\"info\":{\"owner\":\"qinshu\",\"parts\":[{\"count\":13,\"time\":{\"start\":1230002456,\"end\":234001234}}]}}}";// 常用的 Json Path 可以缓存起来重用,类似正则里的 Pattern p = Pattern.compile('regexString')JsonPath codePath = JsonPath.compile("$.code");JsonPath totalPath = JsonPath.compile("$.metainfo.total");@Testpublic void testReadVal() {eq(null, JsonUtil.readVal(null, "code"));eq(null, JsonUtil.readVal(json, null));eq("200", JsonUtil.readVal(json, "code"));eq("20", JsonUtil.readVal(json, "metainfo.total"));eq("qinshu", JsonUtil.readVal(json, "metainfo.info.owner"));eq(null, JsonUtil.readVal("invalid json", "code"));eq(null,JsonUtil.readVal(json, "metainfo.extra.feature"));eq(null, JsonUtil.readValUsingJsonPath(null, "code"));eq(null, JsonUtil.readValUsingJsonPath(json, null));eq("200", JsonUtil.readValUsingJsonPath(json, "code"));eq("20", JsonUtil.readValUsingJsonPath(json, "metainfo.total"));eq("qinshu", JsonUtil.readValUsingJsonPath(json, "metainfo.info.owner"));eq(null, JsonUtil.readValUsingJsonPath("invalid json", "code"));eq(null,JsonUtil.readValUsingJsonPath(json, "metainfo.extra.feature"));eq(200, codePath.read(json));eq(20, totalPath.read(json));eq("qinshu", JsonPath.read(json, "$.metainfo.info.owner"));eq("n1", JsonPath.read(json, "$.list[0].items[0].name"));eq(13, JsonPath.read(json, "$.metainfo.info.parts[0].count"));}}

可见 jsonPath 的功能更加强大,也更加健壮。

JSON解析工具----JSONPath基本使用相关推荐

  1. 一文吃透Json解析工具类合集(FastJson、Jackson、Gson)

    Json解析工具类 前言 一.各个JSON技术的简介 1.1 FastJson角色 1.2 Jackson角色 1.3 Gson角色 二.使用步骤 2.1 引入库 1.FastJson依赖 2.Jac ...

  2. Json解析工具Jackson(使用注解)

    接上一篇文章Json解析工具Jackson(简单应用),jackson在实际应用中给我们提供了一系列注解,提高了开发的灵活性,下面介绍一下最常用的一些注解 @JsonIgnoreProperties ...

  3. JSON解析工具比较,主要GSON和FastJSON

    转自:http://www.cnblogs.com/kunpengit/p/4001680.html 一 .各个JSON技术的简介和优劣 1.json-lib json-lib最开始的也是应用最广泛的 ...

  4. Java:JSON解析工具-org.json

    一.简介 org.json是Java常用的Json解析工具,主要提供JSONObject和JSONArray类,现在就各个类的使用解释如下. 二.准备 1.在使用org.json之前,我们应该先从该网 ...

  5. 自定义Json解析工具

    此博客为博主原创文章,转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/10689536.html fastjson是很好用的json解析工具,只可惜项目中要 ...

  6. json解析工具(json解析工具 python)

    常用的xml,json解析工具有哪些 1.定义介绍 (1).XML定义 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可 ...

  7. Java常用的几种JSON解析工具

    一.Gson:Google开源的JSON解析库 1.添加依赖 <!--gson--> <dependency><groupId>com.google.code.gs ...

  8. FastJson快速上手【Json解析工具】

    目录 一.spring boot工程中引入FastJson依赖 二.调用JSON类的静态方法直接进行json序列化和反序列化 2.1 序列化 2.2 反序列化 三.快速演示: 四.思考 五.web案例 ...

  9. java 自定义json解析注解 复杂json解析 工具类

    java 自定义json解析注解 复杂json解析 工具类 目录 java 自定义json解析注解 复杂json解析 工具类 1.背景 2.需求-各式各样的json 一.一星难度json[json对象 ...

最新文章

  1. OpenStack Newton发布,EasyStack核心代码贡献中国第一!
  2. Maven : 将Jar安装到本地仓库和Jar上传到私服[转]
  3. 计算机视觉与深度学习 | OpenCV3.0.0及高版本安装文件(build/sources)及视频教程
  4. MySQL【案例讲解】分组函数
  5. wait()和waitpid()的参数解析
  6. 【非公开】机顶盒相关
  7. java新入手的三十个基本概念
  8. HBase伪分布式搭建
  9. mysql密码错误怎么回事_mysql密码错误解决方法
  10. linux SCP远程拷贝文件方法及not a regular file 错误解决方法
  11. Endnote X6大客户版破解版+新功能介绍+视频介绍
  12. iphone 扩容测试软件,拯救iPhone 12 64G!闪迪打造的扩容神器上手:轻松省钱
  13. openfire 群聊 java_Openfire即时通讯群聊、单聊、登录、注销的使用方法(Java+Android)...
  14. ASP.NET WEBAPI 跨域请求 405错误
  15. 在网页中引用阿里iconfont字体图标的三种方式
  16. 将复数python与实数运算_python怎么实现复数运算
  17. matlab 三维数组 二维,Matlab相关——三维数组变二维
  18. CentOS6配置NFS服务
  19. 解决UE5项目打包,使用UDP、SocketIO插件报错的问题
  20. 小提琴第一把位音位图

热门文章

  1. 必须收藏!企业邮箱申请的详细流程
  2. 深度学习 图像识别 三
  3. 第四章 舞会上的国王
  4. [六点]Unity零基础实战:古迹探险(一)
  5. 【Android】自定义蜘蛛网图
  6. PC 电脑硬件检测相关工具
  7. 交互媒体技术—2D迷宫冒险游戏
  8. 期权新手学习常见问题
  9. vulnhub靶机Tr0ll1渗透笔记
  10. 重磅消息!天地图2021版正式启用!首次发布高清地图,实现电子地图无级缩放