开篇(扯点闲话)

提起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 ?

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)
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐