因为历史原因和特殊业务逻辑,有个接口会返回如下3种格式的json字符串:
{
"code": 200,
"data": "xxxxxxx",
"msg": "success"
}
{
"code": 200,
"data": {
"info": {
"title": "xxx",
"desc": "xxx"
},
"ext": {
"desc": "xxx"
}
},
"msg": "success"
}
{
"code": 200,
"data": [{
"title": "xxx",
"desc": "xxx"
}, {
"title": "xxx",
"desc": "xxx"
}],
"msg": "success"
}
data这个节点下,可能是一个纯字符串,可能是一个JSONObject,还有可能是一个JSONArray,我们现在要做的是,写一个方法,解析这个json,组装一个统一的返回值供外部调用,问题点就在于怎么判断data节点下是string还是JSONObject还是JSONArray。
前提条件,fastjson用的版本是1.2.83
下面说一下判断方法,刚开始百度搜索出来的结果,大部分是下面这种判断方式:
public static void main(String[] args) {
String objStr = "{\"code\":200,\"data\":{\"info\":{\"title\":\"xxx\",\"desc\":\"xxx\"},\"ext\":{\"desc\":\"xxx\"}},\"msg\":\"success\"}";
String aryStr = "{\"code\":200,\"data\":[{\"title\":\"xxx\",\"desc\":\"xxx\"},{\"title\":\"xxx\",\"desc\":\"xxx\"}],\"msg\":\"success\"}";
String spStr = "{\"code\":200,\"data\":\"xxxxxxx\",\"msg\":\"success\"}";
JSONObject jsonObject = JSON.parseObject(spStr);
Object object = JSON.parse(jsonObject.getString("data"));
if (object instanceof JSONObject) {
System.out.println("JSONObject");
} else if (object instanceof JSONArray) {
System.out.println("JSONArray");
} else {
System.out.println("string");
}
}
上面这种写法,对于data节点下是JSONObject或JSONArray,是能正常判断的,但是如果data下直接是string纯字符串的话,JSON.parse会报错:
Exception in thread "main" com.alibaba.fastjson.JSONException: illegal state. x
at com.alibaba.fastjson.parser.JSONLexerBase.scanHex(JSONLexerBase.java:5109)
at com.alibaba.fastjson.parser.JSONLexerBase.nextToken(JSONLexerBase.java:203)
at com.alibaba.fastjson.parser.DefaultJSONParser.<init>(DefaultJSONParser.java:170)
at com.alibaba.fastjson.parser.DefaultJSONParser.<init>(DefaultJSONParser.java:141)
at com.alibaba.fastjson.JSON.parse(JSON.java:180)
at com.alibaba.fastjson.JSON.parse(JSON.java:191)
at com.alibaba.fastjson.JSON.parse(JSON.java:147)
后来在fastjson的github搜索,发现可以用JSONValidator来做判断,代码如下:
public static void main(String[] args) {
String objStr = "{\"code\":200,\"data\":{\"info\":{\"title\":\"xxx\",\"desc\":\"xxx\"},\"ext\":{\"desc\":\"xxx\"}},\"msg\":\"success\"}";
String aryStr = "{\"code\":200,\"data\":[{\"title\":\"xxx\",\"desc\":\"xxx\"},{\"title\":\"xxx\",\"desc\":\"xxx\"}],\"msg\":\"success\"}";
String spStr = "{\"code\":200,\"data\":\"xxxxxxx\",\"msg\":\"success\"}";
JSONObject jsonObject = JSON.parseObject(spStr);
JSONValidator validator = JSONValidator.from(jsonObject.getString("data"));
JSONValidator.Type jsonType = validator.getType();
System.out.println(jsonType);
if (jsonType == JSONValidator.Type.Object) {
System.out.println("JSONObject");
} else if (jsonType == JSONValidator.Type.Array) {
System.out.println("JSONArray");
} else {
System.out.println("string");
}
}
简单看了一下源码,主要是通过validate()方法来做的判断
public boolean validate() {
if (validateResult != null) {
return validateResult;
}
for (;;) {
if (!any()) {
validateResult = false;
return false;
}
skipWhiteSpace();
count++;
if (eof) {
validateResult = true;
return true;
}
if (supportMultiValue) {
skipWhiteSpace();
if (eof) {
break;
}
continue;
} else {
validateResult = false;
return false;
}
}
validateResult = true;
return true;
}
更加具体详细的代码,请大家移步fastjson的仓库自己看一下
最后结论:
在java中用fastjson,可以通过JSONValidator来判断节点类型