注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

放飞自由

年轻人,如果三年的时间里,没有任何想法,他这一生,就基本这个样子,没有多大改变。

 
 
 

日志

 
 

json-lib字符串转化时间格式问题,转换时间有时候会失效,转换后的时间格式与期望不同(时分秒被转成0)  

2014-05-06 10:35:54|  分类: JAVA后台 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
本文地址:http://houzhiqingjava.blog.163.com/blog/static/16739950720144610135408/
项目中封装了一个公用的转换字符格式的工具类,如下:

/**
* json对象转换JAVA对象

* @param format 时间转换格式
*/
public static Object getObject4JsonString(String jsonString,
Class pojoCalss,String format) {
if(format!=null){
LONG_DATE_PATTERN = format ;
}
Object pojo;
JSONUtils.getMorpherRegistry().registerMorpher( new DateMorpher(new String[] { LONG_DATE_PATTERN }));
JSONObject jsonObject = JSONObject.fromObject(jsonString);
pojo = JSONObject.toBean(jsonObject, pojoCalss);
return pojo;
}

具体什么意思,我不说相信大家也能看出来。

期望:

@Test
public void testConvertFail() {
for(int i = 0; i < 10; i++) {
String msg="[{\"testDateTime\":\"2014-5-5 17:4:1\",\"uploadDateTime\":\"2014-5-5 17:4:5\"}]";
String msg2="[{\"testDateTime\":\"2014-5-4 8:1:40\",\"uploadDateTime\":\"2014-5-4 8:2:15\"}]";

List<BloodPressure> list = JsonUtils.getListJsonDate(msg2, BloodPressure.class, DateUtils.DATE_PATTERN);//yyyy-MM-dd
List<BloodPressure> list2 = JsonUtils.getListJsonDate(msg, BloodPressure.class, DateUtils.LONG_DATE_PATTERN);//yyyy-MM-dd HH:mm:ss

System.out.println("1111=" + list.get(0).getTestDateTime() + ", --- " + list.get(0).getUploadDateTime());
System.out.println("2222=" + list2.get(0).getTestDateTime() + ", --- " + list2.get(0).getUploadDateTime());

}
}

// 在一个方法内(其实我正式项目中没有这样的需求,不在一个方法内),多次调用getObject4JsonString并且传入各种格式的时间。转换时间又是后会失效,但是重启一下系统,有成功了,搞得挺郁闷。

期望得到:

1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 17:04:01 CST 2014, --- Mon May 05 17:04:05 CST 2014


实际得到的:

1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014
1111=Sun May 04 00:00:00 CST 2014, --- Sun May 04 00:00:00 CST 2014
2222=Mon May 05 00:00:00 CST 2014, --- Mon May 05 00:00:00 CST 2014

结果全是yyyy-MM-dd 00:00:00格式的时间,分析代码发现,

List<BloodPressure> list = JsonUtils.getListJsonDate(msg2, BloodPressure.class, DateUtils.DATE_PATTERN);//yyyy-MM-dd
List<BloodPressure> list2 = JsonUtils.getListJsonDate(msg, BloodPressure.class, DateUtils.LONG_DATE_PATTERN);//yyyy-MM-dd HH:mm:ss

执行结果与上面两行代码先后顺序有莫大的关系。猜测可能是线程问题,于是在网上这种搜,各种找没有找到解决办法(竟没有想起来查看源码),然后各种测试JSONUtils.getMorpherRegistry().registerMorpher,一同瞎找人没有找到原因

终于,在看到官方文档和源码时发现一个参数和方法,如下:

// registerMorpher 可以设置参数,是否要重写 刚开始没在意,走读代码是发现了这段代码

JSONUtils.getMorpherRegistry().registerMorpher( new DateMorpher(new String[] { LONG_DATE_PATTERN }), true);


/**
* Register a Morpher for a target <code>Class</code>.<br>
* The target class is the class this Morpher morphs to. If there are another
* morphers registered to that class, it will be appended to a List.
*
* @param morpher a Morpher to register. The method <code>morphsTo()</code>
* is used to associate the Morpher to a target Class
*/
public void registerMorpher( Morpher morpher )
{
registerMorpher( morpher, false );
}


/**
* Register a Morpher for a target <code>Class</code>.<br>
* The target class is the class this Morpher morphs to. If there are another
* morphers registered to that class, it will be appended to a List.
*
* @param morpher a Morpher to register. The method <code>morphsTo()</code>
* is used to associate the Morpher to a target Class
* @param override if registering teh Morpher should override all previously
* registered morphers for the target type
*/
public synchronized void registerMorpher( Morpher morpher, boolean override )
{
List registered = (List) morphers.get( morpher.morphsTo() );
if( override || registered == null ){
registered = new ArrayList();
morphers.put( morpher.morphsTo(), registered );
}
if( !registered.contains( morpher ) ){
registered.add( morpher );
}
}

原来,默认情况下,所有转换的时间格式都是保存在一个集合中,如果不设置的话会一直向集合中保存(重复的不保存),然后转换的时候按照顺序取用,如果第一个转换成功则不再往下查找。

/**
* Morphs and object to the specified target class.<br>
* This method uses reflection to invoke primitive Morphers and Morphers that
* do not implement ObjectMorpher.
*
* @param target the target class to morph to
* @param value the value to morph
* @return an instance of the target class if a suitable Morpher was found
* @throws MorphException if an error occurs during the conversion
*/
public Object morph( Class target, Object value )
{
if( value == null ){
// give the first morpher in the list a shot to convert
// the value as we can't access type information on it
Morpher morpher = getMorpherFor( target );
if( morpher instanceof ObjectMorpher ){
return ((ObjectMorpher) morpher).morph( value );
}else{
try{
Method morphMethod = morpher.getClass()
.getDeclaredMethod( "morph", new Class[] { Object.class } );
return morphMethod.invoke( morpher, new Object[] { value } );
}
catch( Exception e ){
throw new MorphException( e );
}
}
}

Morpher[] morphers = getMorphersFor( target );
for( int i = 0; i < morphers.length; i++ ){
Morpher morpher = morphers[i];
if( morpher.supports( value.getClass() ) ){
if( morpher instanceof ObjectMorpher ){
return ((ObjectMorpher) morpher).morph( value );
}else{
try{
Method morphMethod = morpher.getClass()
.getDeclaredMethod( "morph", new Class[] { Object.class } );
return morphMethod.invoke( morpher, new Object[] { value } );
}
catch( Exception e ){
throw new MorphException( e );
}
}
}
}
return value;
}


这就解释了为什么我输入的结果与我预想的不同,并且与我的执行顺序有关系。

重新修改getListJsonDate方法,如下:

/**
* 将数组JSON字符串转换为List 可以转换日期 默认yyyy-MM-dd HH:mm:ss
* @param jsonString
* @param pojoClass
* @return
*/
public static List getListJsonDate(String jsonString, Class pojoClass,String format){
if(format!=null){
LONG_DATE_PATTERN = format ;
}
JSONUtils.getMorpherRegistry().registerMorpher( new DateMorpher(new String[] { LONG_DATE_PATTERN }), true);
List<Object> list = (List<Object>) JSONArray.toCollection(JSONArray.fromObject(jsonString), pojoClass);
return list ;
}

此时在运行junit方法发现执行结果与预期的相同。

时间关系也有仔细分析源码,也不知道说的对不对,勿喷。



=================================分割线==================================

经过了一天的测试,发现上面的竟然没有起作用,靠,本来以为已经解决的问题狠狠地摆了我一道,重新看源码发现如下方法:

/**
* Deregister the specified Morpher.<br>
* The registry will remove the target <code>Class</code> from the morphers
* Map if it has no other registered morphers.
*
* @param morpher the target Morpher to remove
*/
public synchronized void deregisterMorpher( Morpher morpher )
{
List registered = (List) morphers.get( morpher.morphsTo() );
if( registered != null && !registered.isEmpty() ){
registered.remove( morpher );
if( registered.isEmpty() ){
morphers.remove( morpher.morphsTo() );
}
}
}


如实就有了这样的代码:

/**
* 将JSONArray 转转为 java LIST
* @param ja
* @param pojoClass
* @return
*/
public static List getList4JsonArray(JSONArray ja, Class pojoClass,String format) {

if(!StringUtils.isEmpty(format)) {
JSONUtils.getMorpherRegistry().registerMorpher( new DateMorpher(new String[] { format }));
}

List<Object> list = (List<Object>) JSONArray.toCollection(ja, pojoClass);

if(!StringUtils.isEmpty(format)) {
JSONUtils.getMorpherRegistry().deregisterMorpher( new DateMorpher(new String[] { format }));
}
return list ;
}

注册用完以后再注销,这就是我的策略,本地测试没有发现异常,已升级现网,等待考验,如果不在补充说明已经修改成功了!!

本文地址:http://houzhiqingjava.blog.163.com/blog/static/16739950720144610135408/
  评论这张
 
阅读(353)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017