fastJson遇到的问题

概述

如今的代码开发中,json这种数据类型使用的是愈来愈多,由于它的存取速度都比较快,并且,使用起来很是的简单,今天工做的时候,我就遇到了一个关于json的生产问题,这个问题我以前确实尚未注意过,这边记录下。java

问题再现

再一次远程调用获取相关信息成功以后,须要解析返回的json对象,这个json里面包含了三个元素,一个key为data的jsonObject,表示业务数据,一个Key为success的String,表示是否成功,一个key为resultMessage的失败缘由。正常状况下,这个data是不可能为空的,可是今天不知道怎么了,远端返回的结果里面这个data就是空的,因此解析的时候就出现了以下异常:json

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to com.alibaba.fastjson.JSONObject at com.alibaba.fastjson.JSONObject.getJSONObject(JSONObject.java:109) at com.example.demo.MainTest.main(MainTest.java:10)

 

固然这里要提早说明下,我这边使用的fastJson的版本是1.2.7,出现上面这个错是否是很奇怪,正常不该该返回一个null吗?怎么返回的是String类型不能转成JSONObject呢?app

问题跟踪

问题到了这个地步还有什么好说的呢?只能模仿生产的返回,一步一步的去解析了。测试

 1 public class MainTest {  2     public static void main(String[] args) {
       // 写一个字符串,模拟生产的返回,其中data的值为空
3 String str = "{\"data\": \"\",\"success\": \"true\",\"resultMessage\": \"成功\"}"; 4 // 序列化成json 5 JSONObject result = JSONObject.parseObject(str);
       // 获取data的值
6 JSONObject data = result.getJSONObject("data"); 7 8 System.out.println(data); 9 } 10 }

 

经过debug能够得知,第五行代码是能够正常执行的,返回以下:spa

{"data":"","success":"true","resultMessage":"成功"}debug

这个没有问题,那问题就在第6行代码上了,咱们看一下getJSONObject方法:code

1     public JSONObject getJSONObject(String key) { 2         Object value = map.get(key); 3 
4         if (value instanceof JSONObject) { 5             return (JSONObject) value; 6  } 7 
8         return (JSONObject) toJSON(value); 9     }

 

这边第2行代码根据key获取的value是"",这个显然不是JSONObject类型,直接走最后一行toJSON方法,对象

 1     public static Object toJSON(Object javaObject, ParserConfig mapping) {  2         if (javaObject == null) {  3             return null;  4  }  5 
 6         if (javaObject instanceof JSON) {  7             return javaObject;  8  }  9 
10         if (javaObject instanceof Map) { 11             Map<Object, Object> map = (Map<Object, Object>) javaObject; 12 
13             JSONObject json = new JSONObject(map.size()); 14 
15             for (Map.Entry<Object, Object> entry : map.entrySet()) { 16                 Object key = entry.getKey(); 17                 String jsonKey = TypeUtils.castToString(key); 18                 Object jsonValue = toJSON(entry.getValue()); 19  json.put(jsonKey, jsonValue); 20  } 21 
22             return json; 23  } 24 
25         if (javaObject instanceof Collection) { 26             Collection<Object> collection = (Collection<Object>) javaObject; 27 
28             JSONArray array = new JSONArray(collection.size()); 29 
30             for (Object item : collection) { 31                 Object jsonValue = toJSON(item); 32  array.add(jsonValue); 33  } 34 
35             return array; 36  } 37 
38         Class<?> clazz = javaObject.getClass(); 39 
40         if (clazz.isEnum()) { 41             return ((Enum<?>) javaObject).name(); 42  } 43 
44         if (clazz.isArray()) { 45             int len = Array.getLength(javaObject); 46 
47             JSONArray array = new JSONArray(len); 48 
49             for (int i = 0; i < len; ++i) { 50                 Object item = Array.get(javaObject, i); 51                 Object jsonValue = toJSON(item); 52  array.add(jsonValue); 53  } 54 
55             return array; 56  } 57 
58         if (mapping.isPrimitive(clazz)) { 59             return javaObject; 60  } 61 
62         try { 63             List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null); 64 
65             JSONObject json = new JSONObject(getters.size()); 66 
67             for (FieldInfo field : getters) { 68                 Object value = field.get(javaObject); 69                 Object jsonValue = toJSON(value); 70 
71  json.put(field.getName(), jsonValue); 72  } 73 
74             return json; 75         } catch (IllegalAccessException e) { 76             throw new JSONException("toJSON error", e); 77         } catch (InvocationTargetException e) { 78             throw new JSONException("toJSON error", e); 79  } 80     }

 

这个方法有点长,但其实,真正执行了的也就是38行,获取value对应的class对象,这边返回的java.lang.String,再就是58到60行,判断这个对象是否是基础类型,是就直接返回,那么这边就返回的"",后面强制类型转换的时候固然就会报错。blog

上面这个问题彷佛还很差解决啊,后来看了一下fastJson的几个高版本,已经解决了这个问题,咱们来看一下1.2.51的getJSONObject方法:开发

 1     public JSONObject getJSONObject(String key) {  2         Object value = map.get(key);  3 
 4         if (value instanceof JSONObject) {  5             return (JSONObject) value;  6  }  7 
 8 if (value instanceof String) { 9 return JSON.parseObject((String) value); 10 } 11 
12         return (JSONObject) toJSON(value); 13     }

 

多了8-10行代码,针对String作了下处理,直接返回String解析以后的结果,这样就能够返回理想中的null了。

总结

平时代码开发过程当中,必定要进行异常状况的测试,不可以想固然,要尽可能覆盖每一个分支,要让代码跑不崩溃。

相关文章
相关标签/搜索