我们在平时开发中经常会涉及调用某个REST接口从而获取对应数据的情况,在这个过程中,返回的数据往往都是JSON数据,一般情况下,我们都会针对这些JSON数据定义对应实体类,从而获取我们需要的数据。这种方式对于结构简单的JSON数据是OK的,但是如果遇到下面这种多级嵌套的数据就比较蛋疼了:
{
"a1": {
"b1": {
"c1": {
"d1": "d1"
}
}
},
"a2": {
"b2": {
"c2": {
"d2": ["i1","i2","i3"]
}
}
}
}
那么对于这种情况,有没有比较优雅的处理方式呢?
什么是OGNL表达式
OGNL全称 “对象图导航语言”,我们可以使用其提供的表达式语言获取JAVA对象树中的任意属性或调用其方法。不仅如此,它还能自动实现必要的类型转换,废话不多说,我们来看看如何使用吧。
如何使用
首先引入所需的maven依赖,主要包括jackson和ognl
com.fasterxml.jackson.core
jackson-core
2.11.4
com.fasterxml.jackson.core
jackson-databind
2.11.4
com.fasterxml.jackson.core
jackson-annotations
2.11.4
ognl
ognl
3.1.26
封装JSON反序列化与数据提取的方法
我们封装两个方法:
- parse:将JSON数据反序列化为Map对象;
- getValue:使用OGNL表达式从Map中提取数据;
public class JsonUtils {
private static Logger logger = Logger.getLogger("JsonUtils");
private final static ObjectMapper objectMapper = new ObjectMapper();
public static ObjectMapper getInstance() {
return objectMapper;
}
public static T parse(String jsonStr, Class clazz) throws Exception {
return getInstance().readValue(jsonStr, clazz);
}
public static T getValue(Map map, String path, Class klass) throws Exception {
OgnlContext ctx = new OgnlContext();
ctx.setRoot(map);
T value = (T) Ognl.getValue(path, ctx, ctx.getRoot());
return value;
}
}
测试
public class Demo {
public static void main(String[] args) throws Exception{
String jsonData = "{"a1":{"b1":{"c1":{"d1":"d1"}}},"a2":{"b2":{"c2":{"d2":["i1","i2","i3"]}}}}";
Map map = JsonUtils.parse(jsonData, Map.class);
String s = JsonUtils.getValue(map, "a1.b1.c1.d1", String.class);
System.out.println(s);
List list = JsonUtils.getValue(map, "a2.b2.c2.d2", List.class);
System.out.println(list);
}
}
我们就以开篇展示的多层JSON数据为例进行演示,其中"a1.b1.c1.d1"将取到值为“d1”的字符串数据,“a2.b2.c2.d2”将取到一个列表,运行代码,我们可得到如下结果:
d1
[i1, i2, i3]
小结
我们通过Demo可以看到,使用Ognl表达式可以使我们代码变得更加精炼,避免构造各种复杂实体类的尴尬,关于OGNL的更多用法,小伙伴们可以自行学习。