今天遇到有同事在使用fastjson的JSONObject时,直接在parse方法中传入了一个非json格式的字符串,造成有时候报错,有时候又能正常返回。

问题现象

当你传入一个数值类型时,可以正常解析,当你传入一个非数值类型时,解析就报错了。

public class TestJson {
    public static void main(String[] args) {
        Object parse = JSONObject.parse("12345678");
        System.out.println(parse + ", classType: " + parse.getClass());

        Object parse1 = JSONObject.parse("A12345678");
        System.out.println(parse1 + ", classType: " + parse1.getClass());
    }
}
12345678, classType: class java.lang.Integer
Exception in thread "main" com.alibaba.fastjson.JSONException: syntax error, pos 1, json : A12345678
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1436)
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1322)
	at com.alibaba.fastjson.JSON.parse(JSON.java:152)
	at com.alibaba.fastjson.JSON.parse(JSON.java:162)
	at com.alibaba.fastjson.JSON.parse(JSON.java:131)
	at com.ykc.TestJson.main(TestJson.java:12)

Process finished with exit code 1

其实遇到这个问题时,令我奇怪的是这两个方法都应该报错,因为我一直认为这个方法应该只能解析Json格式的字符串才对。

PS:我完全不知道这位同事是怎么想的,为什么要用parse去解析一个非Json的格式的字符串。。。

简单翻了一下源码,主要就是这个方法,发现原来解析时还兼容了一些其他类型的参数,具体源码就不看了,也没什么特别难以理解的。

   public final void nextToken() {
        sp = 0;

        for (;;) {
            pos = bp;

            if (ch == '/') {
                skipComment();
                continue;
            }

            if (ch == '"') {
                scanString();
                return;
            }

            if (ch == ',') {
                next();
                token = COMMA;
                return;
            }
			
			//支持数值
            if (ch >= '0' && ch <= '9') {
                scanNumber();
                return;
            }

			//这个是负号的意思。。。所以还支持负数
            if (ch == '-') {
                scanNumber();
                return;
            }

            switch (ch) {
                case '\'':
                    if (!isEnabled(Feature.AllowSingleQuotes)) {
                        throw new JSONException("Feature.AllowSingleQuotes is false");
                    }
                    scanStringSingleQuote();
                    return;
                case ' ':
                case '\t':
                case '\b':
                case '\f':
                case '\n':
                case '\r':
                    next();
                    break;
                //还有一些true,false,null这样的
                case 't': // true
                    scanTrue();
                    return;
                case 'f': // false
                    scanFalse();
                    return;
                case 'n': // new,null
                    scanNullOrNew();
                    return;
                case 'T':
                case 'N': // NULL
                case 'S':
                case 'u': // undefined
                    scanIdent();
                    return;
                case '(':
                    next();
                    token = LPAREN;
                    return;
                case ')':
                    next();
                    token = RPAREN;
                    return;
                case '[':
                    next();
                    token = LBRACKET;
                    return;
                case ']':
                    next();
                    token = RBRACKET;
                    return;
                case '{':
                    next();
                    token = LBRACE;
                    return;
                case '}':
                    next();
                    token = RBRACE;
                    return;
                case ':':
                    next();
                    token = COLON;
                    return;
                case ';':
                    next();
                    token = SEMI;
                    return;
                case '.':
                    next();
                    token = DOT;
                    return;
                case '+':
                    next();
                    scanNumber();
                    return;
                case 'x':
                    scanHex();
                    return;
                default:
                    if (isEOF()) { // JLS
                        if (token == EOF) {
                            throw new JSONException("EOF error");
                        }

                        token = EOF;
                        pos = bp = eofPos;
                    } else {
                        if (ch <= 31 || ch == 127) {
                            next();
                            break;
                        }

                        lexError("illegal.char", String.valueOf((int) ch));
                        next();
                    }

                    return;
            }
        }

    }

看一下代码执行效果

public class TestJson {

    public static void main(String[] args) {

        Object parse1 = JSONObject.parse("true");
        System.out.println(parse1 + ", classType: " + parse1.getClass());

        Object parse2 = JSONObject.parse("1");
        System.out.println(parse2 + ", classType: " + parse2.getClass());

        Object parse3 = JSONObject.parse("-1");
        System.out.println(parse3 + ", classType: " + parse3.getClass());

        Object parse4 = JSONObject.parse("1.1");
        System.out.println(parse4 + ", classType: " + parse4.getClass());

        Object parse5 = JSONObject.parse("null");
        System.out.println(parse5);
    }
}
true, classType: class java.lang.Boolean
1, classType: class java.lang.Integer
-1, classType: class java.lang.Integer
1.1, classType: class java.math.BigDecimal
null

Process finished with exit code 0

感觉这个方法有点小坑啊,关键赤裸裸的方法居然一点说明也没有。。。

    public static Object parse(String text) {
        return parse(text, DEFAULT_PARSER_FEATURE);
    }
GitHub 加速计划 / fastj / fastjson
25.69 K
6.51 K
下载
FASTJSON 2.0.x has been released, faster and more secure, recommend you upgrade.
最近提交(Master分支:3 个月前 )
c942c834 - 1 年前
5bc4709b - 1 年前
Logo

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

更多推荐