开篇(扯点闲话)
提起JSON,想必大家脑海里能浮现出几个常用的JSON框架吧 :
- Jackson : Jackson是一个开源的基于Java的json解析和处理类库,它可以轻松的将Java对象转换成json对象或xml文档,同样也可以将json对象或xml文档转换成Java对象,它简单易用并且性能优秀,Jackson社区相对活跃,更新速度也较快,在Spring mvc框架默认也采用了该类库进行json格式的输出。
- Gson : GSON是Google开发的一款开源的JSON解析处理类库,用于转换Java对象和Json对象,即主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。
- FastJson : fastjson是阿里巴巴开源的JSON解析类库,用于解析和处理JSON格式的数据,支持将Java Bean序列化为JSON字符串,也可以将JSON字符串反序列化成JavaBean。
解题思路
选择一种JSON框架,调用它的【字符串 转成 JSON 】的方法,如果方法调用异常则说明不是JSON字符串 。
这思路 应该是很简单的了,你不懂的话,我名字倒着写好吧 。
代码效果对比
特别说明: 以下代码只是判断是否是JSON 对象的字符串,不包含 JSON 数组 的哈 。
这个直接上代码 ,代码一看就懂的那种 , 对比下执行结果,我最终选择了 FastJson
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CheckUtils {
public static boolean isJsonStrByGson(String str) {
try {
JsonElement jsonElement = JsonParser.parseString(str);
return jsonElement.isJsonObject();
} catch (Exception e) {
//字符串解析异常
return false;
}
}
public static boolean isJsonStrByFastjson(String str) {
try {
JSONObject jsonElement = JSONObject.parseObject(str);
return true;
} catch (Exception e) {
return false;
}
}
//验证字符串是否是json字符串
public static void main(String[] args) {
Stream.of("{name:apple,age:12}","{}","{'name':apple}","{\"name\":\"apple\"}").forEach(strItem -> {
System.out.println(strItem + "是否为json object 字符串 : " + isJsonStrByGson(strItem));
System.out.println(strItem + "是否为json object 字符串 : " + isJsonStrByFastjson(strItem));
System.out.println();
});
}
}
来来来,执行结果来啦,有惊喜 :
{name:apple,age:12}是否为json object 字符串 : true
{name:apple,age:12}是否为json object 字符串 : false
{}是否为json object 字符串 : true
{}是否为json object 字符串 : true
{'name':apple}是否为json object 字符串 : true
{'name':apple}是否为json object 字符串 : false
{"name":"apple"}是否为json object 字符串 : true
{"name":"apple"}是否为json object 字符串 : true
有没有发现JsonParser定义的规则也太宽松了吧, 我起初怀疑我自己对JSON的定义有什么误解,后来特意百度了下 。
什么是JSON ?
起码我能从图中读到一条信息:
key : value 中的key 是个string 类型的,需要用双引号括起来啊 。
回头看看JsonParser 的解析结果,我。。。 还是默默地选择 FastJson吧。
但是FastJson经常会报有漏洞,也是头疼的事情,所以结合实际项目考虑下,是否需要使用吧。
如果能确保输入的字符串来源于正确的JSON,比如项目内的Java对象和JSON 互转的话,我觉得是没问题的。如果JSON 字符串来源于外界,含有不确定的因素 , 那就需要小心了 。
尽量选择最新的版本 ,一定要 选择 v1.2.68 之后的版本
目前已知比较大的漏洞有:
(1)autoType
(2)末尾\x 结尾且后面不足2个char的情况 , 会导致oom 。
public class Test {
public static final String DEATH_STRING = "{\"a\":\"\\x1";
public static final String DEATH_STRING_1 = "{\"a\":\"\\x";
public static void main(String[] args) {
try {
Object obj = JSONObject.parse(DEATH_STRING);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.alibaba.fastjson.parser.JSONLexerBase.putChar(JSONLexerBase.java:3319)
at com.alibaba.fastjson.parser.JSONLexerBase.scanString(JSONLexerBase.java:886)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:444)
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1335)
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1301)
at com.alibaba.fastjson.JSON.parse(JSON.java:148)
at com.alibaba.fastjson.JSON.parse(JSON.java:139)
at com.yuki.demo.json.Test.main(Test.java:21)