我是靠谱客的博主 傻傻荷花,这篇文章主要介绍jackson对json转化技巧,现在分享给大家,希望可以做个参考。

好多框架都使用jackson工具进行json转化,现介绍一些使用技巧,本篇使用的jackson版本是2.4.2

涉及到的jar包:cglib-nodep-2.2.jar,jackson-annotations-2.4.2.jar,jackson-core-2.4.2.jar,jackson-databind-2.4.2.jar

本文以数据服务的角度针对后台ElasticSearch和客户需求的场景进行描述


场景1:ElasticSearch查询返回的数据信息太多了,远超过接口需求文档中要返回的信息,如图:


(buckets是个list,下面数据格式都相同,这里就不截图了)

而我方需求是:


可以看出只是某些嵌套中少了几个属性,这时使用jackson的@JsonIgnoreProperties注释可以实现自动忽略功能:使用方法如下,只需在类上面加一行就行

复制代码
1
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@JsonIgnoreProperties(ignoreUnknown = true) public class BucketsT2 { String key; int doc_count; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public int getDoc_count() { return doc_count; } public void setDoc_count(int doc_count) { this.doc_count = doc_count; } }

采用这种方式只需按需求文档定义好反序列化模板,在进行转化时会自动忽略除了模板中的数据以外其他的数据

----------------------------------------------------------------------------------------------------------------------------------

场景2:Elasticsearch查询返回的数据中针对key:value的数据格式较多,有时会发现 有些key会是:make.keyword,color.keyword这种,而反序列化模板要以key为属性名,如图:


这种样式的数据,java编写反序列化模板没法写,命名规则不允许有特殊字符,这就无法直接转换成对象(根本不能这么写)



那除了手动各种readTree一层层通过角标遍历抽出这部分数据以外还有个解决办法:

使用jackon的@JsonProperty注释,作用是当遇到指定属性名时自动转化为反序列化模板中的属性

复制代码
1
2
3
4
5
6
7
8
9
@JsonIgnoreProperties(ignoreUnknown = true) public class BucketsT { String key_as_string; // long key; // int doc_count; @JsonProperty("make.keyword") Make make; @JsonProperty("color.keyword") Make color;

这就会把数据中的mak.keyword转化为mak存起来,同理color.keyword也一样

转化后,通过debug查看反序列化结果:


可以看到make.keyword已经存在了make中,这中方式就可以接收各种奇特的数据

--------------------------------------------------------------------------------------------------------------------------------

场景3:同样以ElasticSearch举例,一般json格式的反序列化模板,对于key:value是这么存的,key="",value="",这样存便于转化


但如果需求文档要求返回的格式是(可能这种格式不是一个好的方案,但是解决方案是要有的)


通过重写jackson Serializer过程,实现该功能,这里提供方法模板,可通过各种场景自定义具体处理逻辑:

首先我们要解决的问题:

1.参与序列化过程,让解析到该位置时,把red和1提取出来

2.动态生成一个类,加入red属性,赋值1

3.在序列化过程中返回新的类,即只替换了{key:red,doc_count:1}=>{read:1},其他整个json嵌套结构都没改变

(1)定义注释,定义序列化方法:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //JacksonAnnotationsInside用于创建注解,jasonSerialize用来指定序列化的类 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) @JacksonAnnotationsInside @JsonSerialize(using = TransformSerializer.class) public @interface TransformField { }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import jackson_test.fieldmiss.object.BucketsT2; import jackson_test.fieldmiss.object.DynamicBean; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class TransformSerializer extends JsonSerializer<List<BucketsT2>> { @Override public void serialize(List<BucketsT2> old, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { //List<BucketsT2>表示我反序列化模板中的一个对象,如果需要修改String,int,或各种类型都可以,替换第一个参数的类型就行 ArrayList<Object> list=new ArrayList<>(); for(BucketsT2 temp:old){ //获取key的值:red String key=temp.getKey(); //获取count的值:1 Integer value=temp.getDoc_count(); //定义动态生成类的属性模板,map中存的数据格式为(属性名,属性类型的class) HashMap<String,Class> map=new HashMap<>(); //(red,Integer.class) map.put(key,value.getClass()); //传给对象生成器 DynamicBean bean=new DynamicBean(map); //把属性值传递给生成器(red,1),会自动把1付给red属性 bean.setValue(key,value); //getObject获得一个拥有一个read属性的类 list.add(bean.getObject()); } //替换了本来old数据的返回结果 jsonGenerator.writeObject(list); } }

(2)动态生成类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import net.sf.cglib.beans.BeanGenerator; import net.sf.cglib.beans.BeanMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class DynamicBean { private Object object = null;//动态生成的类 private BeanMap beanMap = null;//存放属性名称以及属性的类型 public DynamicBean() { super(); } @SuppressWarnings("rawtypes") public DynamicBean(Map propertyMap) { this.object = generateBean(propertyMap); this.beanMap = BeanMap.create(this.object); } /** * 给bean属性赋值 * @param property 属性名 * @param value 值 */ public void setValue(Object property, Object value) { beanMap.put(property, value); } /** * 通过属性名得到属性值 * @param property 属性名 * @return 值 */ public Object getValue(String property) { return beanMap.get(property); } /** * 得到该实体bean对象 * @return */ public Object getObject() { return this.object; } /** * @param propertyMap * @return */ @SuppressWarnings("rawtypes") private Object generateBean(Map<String,Class> propertyMap) { BeanGenerator generator = new BeanGenerator(); Set keySet = propertyMap.keySet(); for (Iterator i = keySet.iterator(); i.hasNext();) { String key = (String) i.next(); Class class_name=propertyMap.get(key); generator.addProperty(key,class_name); } return generator.create(); } }

最后的使用方法:


只需在要转化的对象上加一个注解,这里注意buckets的类型一定要与Serializer相同



最后

以上就是傻傻荷花最近收集整理的关于jackson对json转化技巧的全部内容,更多相关jackson对json转化技巧内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部