GSON -JSON 反序列化-多节点名称支持

引言.最近对接支付宝支付时,发现支付宝接口返回一个泛型的对象.如{"XXX_YYY_response":{},"sign":"AFDSS#QR@43211423142341FAF"},其中 XXX_YYY_response 是动态变化的,即多个值映射到泛型字段.
GSON 提供了 @SerializeName注解来实现.
 1 @Retention(RetentionPolicy.RUNTIME)
 2 @Target({ElementType.FIELD, ElementType.METHOD})
 3 public @interface SerializedName {
 4  
 5 /**
 6 * @return the desired name of the field when it is serialized or deserialized
 7 */
 8 String value();
 9 /**
10 * @return the alternative names of the field when it is deserialized
11 */
12 String[] alternate() default {};
13 }
 
可以给 alternate 赋一个数组来实现.但是每次引入新的支付宝接口时,要变更注解字段 alternate (不能使用变量,因注解字段值必须是常量)的值.不符合开闭原则.
 
使用反射来解决.给泛型对象添加静态注册名字方法,动态改变注解alternate 的值.在具体对象反序化前可以注册一次.
 1 public class AlipayResult<OutParameter extends AlipayBasicOutParameter> {
 2  
 3 private static final Logger LOG= LoggerFactory.getLogger(AlipayResult.class);
 4  
 5 @Expose
 6 private String sign;
 7 private static final String SIGN_TITLE_TAG="sign";
 8  
 9 @Expose
10 @SerializedName(value="",alternate = {})
11 private OutParameter outParameter;
12  
13  
14 @Expose
15 @SerializedName("error_response")
16 private AlipayError errorObject;
17  
18  
19 private static final Set<String> JSON_NAMES= new HashSet<>();
20  
21 static {
22 JSON_NAMES.add("error_response");
23 }
24  
25  
26  
27 public static synchronized final void registerOutParameterAlternate(final String namespace){
28 try {
29 JSON_NAMES.add(namespace);
30 Field field = AlipayResult.class.getDeclaredField("outParameter");
31 field.setAccessible(true);
32 SerializedName serialName = field.getDeclaredAnnotation(SerializedName.class);
33 String[] ns = serialName.alternate();
34 for (String item : ns) {
35 if (item.equals(namespace)) {
36 return;
37 }
38 }
39 InvocationHandler h = Proxy.getInvocationHandler(serialName);
40 // 获取 AnnotationInvocationHandler 的 memberValues 字段
41 Field hField = h.getClass().getDeclaredField("memberValues");
42 // 因为这个字段事 private final 修饰,所以要打开权限
43 hField.setAccessible(true);
44 // 获取 memberValues
45 Map memberValues = (Map) hField.get(h);
46 // 修改 value 属性值
47 List<String> target =new ArrayList<String>();
48 if(null!=ns&&ns.length>0){
49 for (String i:ns){
50 target.add(i);
51 }
52 }
53 target.add(namespace);
54 String[] alternateArr = target.toArray(new String[0]);
55 memberValues.put("alternate", alternateArr);
56 if (LOG.isInfoEnabled()) {
57 LOG.info("alternate value is " + alternateArr);
58 }
59 }catch (Throwable throwable){
60 throw new RuntimeException(throwable);
61 }
62 }
63  
64 private static final String AlipayResponseNameSpaces="";
65  
66 public String getSign() {
67 return sign;
68 }
69  
70 public void setSign(String sign) {
71 this.sign = sign;
72 }
73  
74 public OutParameter getOutParameter() {
75 return outParameter;
76 }
77  
78 public void setOutParameter(OutParameter outParameter) {
79 this.outParameter = outParameter;
80 }
 
原文地址:https://www.cnblogs.com/hhbk/p/7814731.html