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,時間的一個實例,即當前時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM