基于注解实现jackson动态JsonProperty

@JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,但是值是固定的,(不贴代码,可以看其他博客)

目前跟某公司做接口对接时数据格式是这样的:

    接口A:                            接口B:

              

映射实体对象  :(这里用到lombok工具)

报文第三个字段与具体的pojo类有关,@JsonProperty在这里显然无法实现;

这里写两种序列化方式:

第一种 : 注解@JsonAnyGetter  (自己了解下这个注解,这里变相使用了下)

映射实体对象类做下调整

测试代码(注意测试时每个类里加些属性,否则抛异常):

第二种 : 自定义注解来实现(我不想做pojo类的变动,感觉Map怪怪的,因为这里接口对接这里是一个对象)

先贴测试代码:

这里@DynamicJsonProperty为自定义的注解,(不了解自定义注解的可以先百度下"jackson自定义序列化注解实现自己的序列逻辑")

下面是该注解相应的代码:

  1 import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
2 import com.fasterxml.jackson.core.JsonGenerator;
3 import com.fasterxml.jackson.core.json.UTF8JsonGenerator;
4 import com.fasterxml.jackson.core.json.WriterBasedJsonGenerator;
5 import com.fasterxml.jackson.databind.BeanProperty;
6 import com.fasterxml.jackson.databind.JsonMappingException;
7 import com.fasterxml.jackson.databind.JsonSerializer;
8 import com.fasterxml.jackson.databind.SerializerProvider;
9 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
10 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
11 import com.sinosoft.ehs.utils.Reflector;
12 import com.sinosoft.ehs.utils.Strings;
13
14 import java.io.IOException;
15 import java.lang.annotation.*;
16 import java.util.function.Function;
17
18 @Documented
19 @Retention(RetentionPolicy.RUNTIME)
20 @Target({ElementType.FIELD,ElementType.METHOD})
21 @JacksonAnnotationsInside
22 @JsonSerialize(using = DynamicJsonProperty.DynamicJsonPropertySerializer.class)
23 public @interface DynamicJsonProperty {
24
25 AS[] value() default {};
26
27 Strategy strategy() default Strategy.CLASS_SIMPLE_NAME_LOWERCASE;
28
29
30 @interface AS{
31
32 String name();
33
34 Class<?> value();
35 }
36
37 @Retention(RetentionPolicy.RUNTIME)
38 @interface Name{
39 String value();
40 }
41
42 interface KeyName{
43 String jsonPropertyName();
44 }
45
46
47 enum Strategy{
48
49 CLASS_NAME(object -> object.getClass().getName()),
50 CLASS_SIMPLE_NAME(object -> object.getClass().getSimpleName()),
51 CLASS_SIMPLE_NAME_LOWERCASE(object -> object.getClass().getSimpleName().toLowerCase()),
52 CLASS_SIMPLE_NAME_UPPERCASE(object -> object.getClass().getSimpleName().toUpperCase());
53
54 private Function<Object,String> function;
55
56 Strategy(Function<Object,String> function){
57 this.function = function;
58 }
59
60 public String getName(Object object){
61 if(object==null)
62 return null;
63 return function.apply(object);
64 }
65
66 }
67
68 class DynamicJsonPropertySerializer extends JsonSerializer<Object> implements ContextualSerializer {
69 /**key值是否重置*/
70 private boolean gotName;
71 private DynamicJsonProperty annotation;
72 /**原先的key值*/
73 private String originalName;
74
75
76 @Override
77 public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
78 if(value != null && !gotName){
79 String name = getKeyName(value);
80 if(jsonGenerator instanceof WriterBasedJsonGenerator){
81 char[] _outputBuffer = Reflector.getFieldValue(jsonGenerator,"_outputBuffer",char[].class);
82 char _quoteChar = Reflector.getFieldValue(jsonGenerator,"_quoteChar",char.class);
83 int start = String.valueOf(_outputBuffer).lastIndexOf(originalName);
84 int end = start+name.length()+1;
85 Reflector.setFieldValue(jsonGenerator,"_outputTail",end);
86
87 for(int i=0;i<name.length();i++){
88 _outputBuffer[start+i] = name.charAt(i);
89 }
90 _outputBuffer[start+name.length()] = _quoteChar;
91 }
92
93 if(jsonGenerator instanceof UTF8JsonGenerator){
94 byte[] _outputBuffer = Reflector.getFieldValue(jsonGenerator,"_outputBuffer",byte[].class);
95 int _outputTail = Reflector.getFieldValue(jsonGenerator,"_outputTail",int.class);
96
97 byte _quoteChar = Reflector.getFieldValue(jsonGenerator,"_quoteChar",byte.class);
98 System.err.println(new String(_outputBuffer,"UTF-8"));
99 int startIndex = getStartIndex(_outputBuffer, _outputTail, 1)+1;
100 byte[] nameBytes = name.getBytes("UTF-8");
101 int end = startIndex+nameBytes.length+1;
102 Reflector.setFieldValue(jsonGenerator,"_outputTail",end);
103
104 for(int i=0;i<nameBytes.length;i++){
105 _outputBuffer[startIndex+i] = nameBytes[i];
106 }
107 _outputBuffer[startIndex+nameBytes.length] = _quoteChar;
108
109
110 }
111 }
112 jsonGenerator.writeObject(value);
113 }
114
115
116 @Override
117 public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
118 annotation = beanProperty.getAnnotation(DynamicJsonProperty.class);
119 /**
120 * PropertyName fullName = beanProperty.getFullName();
121 * PropertyName._simpleName 字段即为key健的值,反射直接赋值即可实现,
122 * 不过这里未获取操作的Object对象,只能获取Field或者Method
123 * createContextual优先执行,serialize之后执行,这里顺序问题也不能操作
124 * 之后在细看程序研究,或者有大牛能解决的联系学习下
125 */
126 originalName = beanProperty.getName();
127 return this;
128 }
129
130 private String getKeyName(Object value){
131 Class<?> valueType = value.getClass();
132 AS[] asAnnotations = annotation.value();
133 for(int i=0;i<asAnnotations.length;i++){
134 if(asAnnotations[i].value() == valueType)
135 return asAnnotations[i].name();
136 }
137
138 Annotation[] annotations = valueType.getAnnotations();
139
140 Name nameAnnotation = valueType.getAnnotation(DynamicJsonProperty.Name.class);
141 if(nameAnnotation!=null)
142 return nameAnnotation.value();
143
144 if(value instanceof DynamicJsonProperty.KeyName){
145 String name = ((DynamicJsonProperty.KeyName)value).jsonPropertyName();
146 if(!Strings.isBlank(name))
147 return name;
148 }
149
150 return annotation.strategy().getName(value);
151 }
152
153 private int getStartIndex(byte[] _outputBuffer,int _outputTail,int index){
154 int currentIndex = 0;
155 for(int i=_outputTail;i>=0;i--){
156 if(_outputBuffer[i] == 34){
157 if(currentIndex == index)
158 return i;
159 currentIndex++;
160 }
161 }
162 return -1;
163 }
164
165 }
166
167
168 }

四种写法实例:

  

 注意 :  以上四种方法字段data均需加注解@DynamicJsonProperty

反序列话直接加set方法即可

这里是通过反射重新赋值来实现,不同版本可能存在差异或者异常,测试用maven依赖

附反射代码:

    public static Field getField(Class<?> formType,String fieldName) throws NoSuchFieldException{
if(formType == Object.class)
throw new NoSuchFieldException();
Field[] fields = formType.getDeclaredFields();
for(int i=0;i<fields.length;i++){
if(fields[i].getName().equals(fieldName))
return fields[i];
}
return getField(formType.getSuperclass(),fieldName);
} @SuppressWarnings("unchecked")
public static <T> T getFieldValue(Object srcObject,String fieldName,Class<T> fieldType){
try {
Field field = getField(srcObject.getClass(),fieldName);
field.setAccessible(true);
return (T) field.get(srcObject);
} catch (Exception e) {
throw new RuntimeException(e);
}
} public static void setFieldValue(Object srcObject,String fieldName,Object fieldValue){
try {
Field field = getField(srcObject.getClass(),fieldName);
field.setAccessible(true);
field.set(srcObject, fieldValue);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

最后这个问题如能解决,麻烦留言下解决的代码

    

最新文章

  1. Wireshark
  2. Python的字节编译
  3. java-GUI图形用户界面
  4. MyBatis与Hibernate对比
  5. 避免硬编码你的PostgreSQL数据库密码
  6. POJ 3678 Katu Puzzle (2-SAT,常规)
  7. hdu 4908 BestCoder Sequence
  8. bzoj 1020-1029
  9. JavaScript 框架------------AngularJS(上)
  10. pads&#160;layout 自动打地孔
  11. Object_C与JavaScript交互使用总结
  12. jqGrid 奇淫巧技
  13. 定义function的层级
  14. zabbix出现中文不能选的情况
  15. leetcode-917-仅仅反转字母
  16. android学习-进程/线程管理-完整
  17. java SE 入门之语言与环境(第一篇)
  18. java随机数的有趣用法
  19. Windows安装MySQL解压版
  20. R语言实战实现基于用户的简单的推荐系统(数量较少)

热门文章

  1. pgsql学习
  2. 分享几个下载豆瓣资源的chrome插件
  3. C语言编译步骤
  4. vue 之 v-model
  5. 01_Keil与Proteus联合仿真的注意事项
  6. Excel vba call Python script on Mac
  7. thinkphp5.x在函数禁用的情况下绕过
  8. Docker之Alpine制作jre镜像(瘦身)+自定义镜像上传阿里云
  9. Java的参数传递是值传递还是引用传递?
  10. Python - pip 批量更新