json-lib json反序列化——日期转换

将json格式的字符串转为对象,其中key-value有将String的日期转为Date类型,怪现象就是,转出来的Date类型的值是当前的系统时间。

网上有许多答案,在反序列化之前需要注册Date解析类型,也就是这段代码:

JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[]{"yyyy-MM-dd"}));

发现并没啥用,最后发现一切的原因都是因为这个方法用错了。

 

仔细看源码,原来在json-lib中一个MorpherRegistry类,所有的转化类型都存在Map morphers中。

在第一次使用JSONObject静态方法时,就会自动注册默认的类型,JSONObject.java中调用了JSONUtils.java,JSONUtils.java源码中有这么一段:

static {
    MorphUtils.registerStandardMorphers(morpherRegistry);
}

在MorphUtils.java代码是:

 1 public class MorphUtils {
 2     public static final BigDecimal BIGDECIMAL_ONE = new BigDecimal("1");
 3     public static final BigDecimal BIGDECIMAL_ZERO = new BigDecimal("0");
 4 
 5     public static void registerStandardMorphers(MorpherRegistry morpherRegistry) {
 6         morpherRegistry.clear();
 7         registerStandardPrimitiveMorphers(morpherRegistry);
 8         registerStandardPrimitiveArrayMorphers(morpherRegistry);
 9         registerStandardObjectMorphers(morpherRegistry);
10         registerStandardObjectArrayMorphers(morpherRegistry);
11     }
12 
13     public static void registerStandardObjectArrayMorphers(MorpherRegistry morpherRegistry) {
14         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new BooleanObjectMorpher(Boolean.FALSE)));
15         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new CharacterObjectMorpher(new Character('\u0000'))));
16         morpherRegistry.registerMorpher(new ObjectArrayMorpher(StringMorpher.getInstance()));
17         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Byte.class, new Byte((byte)0))));
18         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Short.class, new Short((short)0))));
19         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Integer.class, new Integer(0))));
20         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Long.class, new Long(0L))));
21         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Float.class, new Float(0.0F))));
22         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Double.class, new Double(0.0D))));
23         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(BigInteger.class, BigInteger.ZERO)));
24         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(BigDecimal.class, BIGDECIMAL_ZERO)));
25         morpherRegistry.registerMorpher(new ObjectArrayMorpher(ClassMorpher.getInstance()));
26     }
27 
28     public static void registerStandardObjectMorphers(MorpherRegistry morpherRegistry) {
29         morpherRegistry.registerMorpher(new BooleanObjectMorpher(Boolean.FALSE));
30         morpherRegistry.registerMorpher(new CharacterObjectMorpher(new Character('\u0000')));
31         morpherRegistry.registerMorpher(StringMorpher.getInstance());
32         morpherRegistry.registerMorpher(new NumberMorpher(Byte.class, new Byte((byte)0)));
33         morpherRegistry.registerMorpher(new NumberMorpher(Short.class, new Short((short)0)));
34         morpherRegistry.registerMorpher(new NumberMorpher(Integer.class, new Integer(0)));
35         morpherRegistry.registerMorpher(new NumberMorpher(Long.class, new Long(0L)));
36         morpherRegistry.registerMorpher(new NumberMorpher(Float.class, new Float(0.0F)));
37         morpherRegistry.registerMorpher(new NumberMorpher(Double.class, new Double(0.0D)));
38         morpherRegistry.registerMorpher(new NumberMorpher(BigInteger.class, BigInteger.ZERO));
39         morpherRegistry.registerMorpher(new NumberMorpher(BigDecimal.class, BIGDECIMAL_ZERO));
40         morpherRegistry.registerMorpher(ClassMorpher.getInstance());
41     }
42 
43     public static void registerStandardPrimitiveArrayMorphers(MorpherRegistry morpherRegistry) {
44         morpherRegistry.registerMorpher(new BooleanArrayMorpher(false));
45         morpherRegistry.registerMorpher(new CharArrayMorpher('\u0000'));
46         morpherRegistry.registerMorpher(new ByteArrayMorpher((byte)0));
47         morpherRegistry.registerMorpher(new ShortArrayMorpher((short)0));
48         morpherRegistry.registerMorpher(new IntArrayMorpher(0));
49         morpherRegistry.registerMorpher(new LongArrayMorpher(0L));
50         morpherRegistry.registerMorpher(new FloatArrayMorpher(0.0F));
51         morpherRegistry.registerMorpher(new DoubleArrayMorpher(0.0D));
52     }
53 
54     public static void registerStandardPrimitiveMorphers(MorpherRegistry morpherRegistry) {
55         morpherRegistry.registerMorpher(new BooleanMorpher(false));
56         morpherRegistry.registerMorpher(new CharMorpher('\u0000'));
57         morpherRegistry.registerMorpher(new ByteMorpher((byte)0));
58         morpherRegistry.registerMorpher(new ShortMorpher((short)0));
59         morpherRegistry.registerMorpher(new IntMorpher(0));
60         morpherRegistry.registerMorpher(new LongMorpher(0L));
61         morpherRegistry.registerMorpher(new FloatMorpher(0.0F));
62         morpherRegistry.registerMorpher(new DoubleMorpher(0.0D));
63     }
64 
65     private MorphUtils() {
66     }
67 }
View Code

 

因此,在JSONUtils初始化的时候,就将默认类型放在了MorpherRegistry的morphs中。从上面的代码可以看出来,Date不属于默认的类型。因此,这里可以看出来,在做json反序列化时,如果有需要转成Date类型的String,就需要自己手动注册一个DateMorpher。

怎么加是一个问题了。其实在文章最前面提到的网上的解决方案也并没有错,看下源码就知道了,为啥这个方法却在我使用的时候不起作用了。

在MorpherRegistry.java中Morpher注册源码:

 

 1 public class MorpherRegistry implements Serializable {
 2     private static final long serialVersionUID = -3894767123320768419L;
 3     private Map morphers = new HashMap();
 4 
 5     public MorpherRegistry() {
 6     }
 7 
 8     public synchronized Morpher[] getMorphersFor(Class clazz) {
 9         List registered = (List)this.morphers.get(clazz);
10         if(registered != null && !registered.isEmpty()) {
11             Morpher[] morphs = new Morpher[registered.size()];
12             int k = 0;
13 
14             for(Iterator i = registered.iterator(); i.hasNext(); morphs[k++] = (Morpher)i.next()) {
15                 ;
16             }
17 
18             return morphs;
19         } else {
20             return new Morpher[]{IdentityObjectMorpher.getInstance()};
21         }
22     }
23 
24     public Object morph(Class target, Object value) {
25         if(value == null) {
26             Morpher var9 = this.getMorpherFor(target);
27             if(var9 instanceof ObjectMorpher) {
28                 return ((ObjectMorpher)var9).morph(value);
29             } else {
30                 try {
31                     Method var10 = var9.getClass().getDeclaredMethod("morph", new Class[]{class$java$lang$Object == null?(class$java$lang$Object = class$("java.lang.Object")):class$java$lang$Object});
32                     return var10.invoke(var9, new Object[]{value});
33                 } catch (Exception var7) {
34                     throw new MorphException(var7);
35                 }
36             }
37         } else {
38             Morpher[] morphers = this.getMorphersFor(target);
39 
40             for(int i = 0; i < morphers.length; ++i) {
41                 Morpher morpher = morphers[i];
42                 if(morpher.supports(value.getClass())) {
43                     if(morpher instanceof ObjectMorpher) {
44                         return ((ObjectMorpher)morpher).morph(value);
45                     }
46 
47                     try {
48                         Method e = morpher.getClass().getDeclaredMethod("morph", new Class[]{class$java$lang$Object == null?(class$java$lang$Object = class$("java.lang.Object")):class$java$lang$Object});
49                         return e.invoke(morpher, new Object[]{value});
50                     } catch (Exception var8) {
51                         throw new MorphException(var8);
52                     }
53                 }
54             }
55 
56             return value;
57         }
58     }
59 
60     public synchronized void registerMorpher(Morpher morpher, boolean override) {
61         Object registered = (List)this.morphers.get(morpher.morphsTo());
62         if(override || registered == null) {
63             registered = new ArrayList();
64             this.morphers.put(morpher.morphsTo(), registered);
65         }
66 
67         if(!((List)registered).contains(morpher)) {
68             ((List)registered).add(morpher);
69         }
70 
71     }
72 }
View Code

 

在registerMorpher()中,可以看出来morpher事实上是一个Map<Object.class, List<Morpher>>的结构,而在使用morph()将String转为对象时取得是最先符合的类型。因此,前文中提到提到的网络解决方法,在morpher.get(Object.class)不为空时,只是对List<Morpher> registered进行add操作。由此,在进行转化操作时,就不一定获取到正确的对应类型。因此从registerMorpher()方法中可以看出,我们只需要override设置为false,这个问题也就解决了。

假如我们在调试的时候,需要修改这个注册类型,且又不想重启服务的时候,这样写就很方便了。

JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[]{"yyyy-MM-dd"}), true);

这样就能获取到正确的转化类型。

 

前文还提到一个问题,就是时间转化,变成了当前系统的时间。在MorpherRegistry进行反序列时,morph()中

((ObjectMorpher)morpher).morph(value)

调用的方法是BeanMorpher.morph方法,在BeanMorpher.morp()方法中

 1 public Object morph(Object sourceBean) {
 2         if(sourceBean == null) {
 3             return null;
 4         } else if(!this.supports(sourceBean.getClass())) {
 5             throw new MorphException("unsupported class: " + sourceBean.getClass().getName());
 6         } else {
 7             Object targetBean = null;
 8 
 9             try {
10                 targetBean = this.beanClass.newInstance();
11                 PropertyDescriptor[] e = PropertyUtils.getPropertyDescriptors(this.beanClass);
12 
13                 for(int i = 0; i < e.length; ++i) {
14                     PropertyDescriptor targetPd = e[i];
15                     String name = targetPd.getName();
16                     if(targetPd.getWriteMethod() == null) {
17                         log.info("Property \'" + this.beanClass.getName() + "." + name + "\' has no write method. SKIPPED.");
18                     } else {
19                         Class sourceType = null;
20                         if(sourceBean instanceof DynaBean) {
21                             DynaBean targetType = (DynaBean)sourceBean;
22                             DynaProperty value = targetType.getDynaClass().getDynaProperty(name);
23                             if(value == null) {
24                                 log.warn("DynaProperty \'" + name + "\' does not exist. SKIPPED.");
25                                 continue;
26                             }
27 
28                             sourceType = value.getType();
29                         } else {
30                             PropertyDescriptor var12 = PropertyUtils.getPropertyDescriptor(sourceBean, name);
31                             if(var12 == null) {
32                                 log.warn("Property \'" + sourceBean.getClass().getName() + "." + name + "\' does not exist. SKIPPED.");
33                                 continue;
34                             }
35 
36                             if(var12.getReadMethod() == null) {
37                                 log.warn("Property \'" + sourceBean.getClass().getName() + "." + name + "\' has no read method. SKIPPED.");
38                                 continue;
39                             }
40 
41                             sourceType = var12.getPropertyType();
42                         }
43 
44                         Class var13 = targetPd.getPropertyType();
45                         Object var14 = PropertyUtils.getProperty(sourceBean, name);
46                         this.setProperty(targetBean, name, sourceType, var13, var14);
47                     }
48                 }
49 
50                 return targetBean;
51             } catch (MorphException var10) {
52                 throw var10;
53             } catch (Exception var11) {
54                 throw new MorphException(var11);
55             }
56         }
57     }
View Code

 

 sourceBean不属于DynaBean,且var12的值也为null,因此返回的值就是targetBean,时间的一个实例,即当前时间。

posted @ 2015-11-11 09:48  Jeniss  阅读(2666)  评论(0编辑  收藏  举报