判断一个字符串是否是JSON字符串的坑

本文对比了Jackson、Gson和FastJson三种JSON框架在处理JSON字符串时的表现。通过代码示例展示了如何判断一个字符串是否为合法的JSON对象,并分析了各框架在解析规则上的差异。最终,FastJson因其更严格的解析标准和性能优势被推荐使用,但需注意其安全漏洞问题。
摘要由CSDN通过智能技术生成

开篇(扯点闲话)

提起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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值