fastjson java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode

llew8vvj  于 2021-11-27  发布在  Java
关注(0)|答案(5)|浏览(389)

use 1.2.7 source code in mysql project,now used 1.2.29 jar
the fastjson source code is throws exception , like this。
Caused by: java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1827) ~[?:1.8.0_102]
at java.util.HashMap$TreeNode.treeify(HashMap.java:1944) ~[?:1.8.0_102]
at java.util.HashMap$TreeNode.split(HashMap.java:2170) ~[?:1.8.0_102]
at java.util.HashMap.resize(HashMap.java:713) ~[?:1.8.0_102]
at java.util.HashMap.putVal(HashMap.java:662) ~[?:1.8.0_102]
at java.util.HashMap.put(HashMap.java:611) ~[?:1.8.0_102]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONParser.getUnifyRef(CacheJSONParser.java:703) ~[classes/:?]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONParser.setUnifyStringValue(CacheJSONParser.java:667) ~[classes/:?]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONParser.parseMap(CacheJSONParser.java:396) ~[classes/:?]
at com.huawei.appmarket.cachesys.datamanager.CacheMapDeserializer.deserialze(CacheMapDeserializer.java:39) ~[classes/:?]
at com.alibaba.fastjson.parser.deserializer.MapDeserializer.deserialze(MapDeserializer.java:39) ~[fastjson-1.2.29.jar:?]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONParser.parseMap(CacheJSONParser.java:298) ~[classes/:?]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONParser.parse(CacheJSONParser.java:81) ~[classes/:?]
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1301) ~[fastjson-1.2.29.jar:?]
at com.huawei.appmarket.cachesys.datamanager.CacheJSONProcesser.toObject(CacheJSONProcesser.java:176) ~[classes/:?]
at com.huawei.appmarket.cachesys.DataUtils.write(DataUtils.java:299) ~[classes/:?]
at com.huawei.appmarket.cachesys.LoadInterfaceData.loadNewAppEditorDesc(LoadInterfaceData.java:1010) ~[classes/:?]
... 10 more

mjqavswn

mjqavswn1#

com.huawei.appmarket.cachesys.datamanager.CacheJSONParser
com.alibaba.fastjson.parser.deserializer.MapDeserializer
这两个类的代码能发给我看一下吗?

hyrbngr7

hyrbngr72#

@wenshao
com.huawei.appmarket.cachesys.datamanager.CacheJSONParser: 这个类的代码

public class CacheJSONParser extends DefaultJSONParser
{
    private static HashMap<String, String> allCacheStr = new HashMap<String, String>();

    public CacheJSONParser(String input)
    {
        super(input);
    }

    public CacheJSONParser(final String input, final ParserConfig config)
    {
        super(input, config);
    }

    @SuppressWarnings("rawtypes")
    public Object parse(Object fieldName)
    {
        final JSONLexer lexer = getLexer();
        switch (lexer.token())
        {
        case SET:
            lexer.nextToken();
            HashSet<Object> set = new HashSet<Object>();
            parseArray(set, fieldName);
            return set;
        case TREE_SET:
            lexer.nextToken();
            TreeSet<Object> treeSet = new TreeSet<Object>();
            parseArray(treeSet, fieldName);
            return treeSet;
        case LBRACKET:
            List collection = new ArrayList();
            parseCollection(collection, fieldName);
            return unmodify(collection);
        case LBRACE:
            Map map = new HashMap();
            return parseMap(map, fieldName);
        case LITERAL_INT:
            Number intValue = lexer.integerValue();
            lexer.nextToken();
            return intValue;
        case LITERAL_FLOAT:
            Object value = lexer.decimalValue(isEnabled(Feature.UseBigDecimal));
            lexer.nextToken();
            return value;
        case LITERAL_STRING:
            return literalString(lexer);
        case NULL:
            lexer.nextToken();
            return null;
        case TRUE:
            lexer.nextToken();
            return Boolean.TRUE;
        case FALSE:
            lexer.nextToken();
            return Boolean.FALSE;
        case NEW:
            lexer.nextToken(JSONToken.IDENTIFIER);

            if (lexer.token() != JSONToken.IDENTIFIER)
            {
                throw new JSONException("syntax error");
            }
            lexer.nextToken(JSONToken.LPAREN);

            accept(JSONToken.LPAREN);
            long time = ((Number) lexer.integerValue()).longValue();
            accept(JSONToken.LITERAL_INT);

            accept(JSONToken.RPAREN);

            return new Date(time);
        case EOF:
            if (lexer.isBlankInput())
            {
                return null;
            }
            throw new JSONException("unterminated json string, info: " + lexer.info());
        case ERROR:
        default:
            throw new JSONException("syntax error, info " + lexer.info());
        }
    }

    private Object literalString(final JSONLexer lexer)
    {
        String stringLiteral = lexer.stringVal();
        lexer.nextToken(JSONToken.COMMA);

        if (lexer.isEnabled(Feature.AllowISO8601DateFormat))
        {
            JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
            try
            {
                if (iso8601Lexer.scanISO8601DateIfMatch())
                {
                    return iso8601Lexer.getCalendar().getTime();
                }
            }
            finally
            {
                iso8601Lexer.close();
            }
        }

        return stringLiteral;
    }

    @SuppressWarnings({ "rawtypes" })
    public Object parseMap(final Map object, Object fieldName)
    {
        JSONScanner lexer = (JSONScanner) this.lexer;

        if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA)
        {
            throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
        }

        ParseContext context = this.getContext();
        try
        {
            boolean setContextFlag = false;
            for (;;)
            {
                lexer.skipWhitespace();
                char ch = lexer.getCurrent();
                ch = onAllowAC(lexer, ch);

                boolean isObjectKey = false;
                Object key;
                if (ch == '"')
                {
                    key = lexer.scanSymbol(symbolTable, '"');
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ':')
                    {
                        throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);
                    }
                }
                else if (ch == '}')
                {
                    lexer.next();
                    lexer.resetStringPosition();
                    lexer.nextToken();
                    return unmodify(object);
                }
                else if (ch == '\'')
                {
                    if (!isEnabled(Feature.AllowSingleQuotes))
                    {
                        throw new JSONException("syntax error");
                    }

                    key = lexer.scanSymbol(symbolTable, '\'');
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ':')
                    {
                        throw new JSONException("expect ':' at " + lexer.pos());
                    }
                }
                else if (ch == EOI)
                {
                    throw new JSONException("syntax error");
                }
                else if (ch == ',')
                {
                    throw new JSONException("syntax error");
                }
                else if ((ch >= '0' && ch <= '9') || ch == '-')
                {
                    lexer.resetStringPosition();
                    lexer.scanNumber();
                    if (lexer.token() == JSONToken.LITERAL_INT)
                    {
                        key = lexer.integerValue();
                    }
                    else
                    {
                        key = lexer.decimalValue(true);
                    }
                    ch = lexer.getCurrent();
                    if (ch != ':')
                    {
                        throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);
                    }
                }
                else if (ch == '{' || ch == '[')
                {
                    lexer.nextToken();
                    key = parse();
                    isObjectKey = true;
                }
                else
                {
                    if (!isEnabled(Feature.AllowUnQuotedFieldNames))
                    {
                        throw new JSONException("syntax error");
                    }

                    key = lexer.scanSymbolUnQuoted(symbolTable);
                    lexer.skipWhitespace();
                    ch = lexer.getCurrent();
                    if (ch != ':')
                    {
                        throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
                    }
                }

                if (!isObjectKey)
                {
                    lexer.next();
                    lexer.skipWhitespace();
                }

                ch = lexer.getCurrent();

                lexer.resetStringPosition();

                if ("@type".equals(key))
                {
                    String typeName = lexer.scanSymbol(symbolTable, '"');
                    Class<?> clazz = TypeUtils.loadClass(typeName);

                    if (clazz == null)
                    {
                        setUnifyStringValue(object, "@type", typeName);
                        continue;
                    }

                    lexer.nextToken(JSONToken.COMMA);
                    if (lexer.token() == JSONToken.RBRACE)
                    {
                        lexer.nextToken(JSONToken.COMMA);
                        try
                        {
                            return unmodify(clazz.newInstance());
                        }
                        catch (Exception e)
                        {
                            throw new JSONException("create instance error", e);
                        }
                    }

                    this.setResolveStatus(TypeNameRedirect);

                    if (this.context != null && !(fieldName instanceof Integer))
                    {
                        this.popContext();
                    }

                    ObjectDeserializer deserializer = config.getDeserializer(clazz);
                    return unmodify(deserializer.deserialze(this, clazz, fieldName));
                }

                if ("$ref".equals(key))
                {
                    lexer.nextToken(JSONToken.LITERAL_STRING);
                    if (lexer.token() == JSONToken.LITERAL_STRING)
                    {
                        String ref = lexer.stringVal();
                        lexer.nextToken(JSONToken.RBRACE);

                        Object refValue = null;
                        if ("@".equals(ref))
                        {
                            if (this.getContext() != null)
                            {
                                refValue = this.getContext().object;
                            }
                        }
                        else if ("..".equals(ref))
                        {
                            ParseContext parentContext = context.parent;
                            if (parentContext.object != null)
                            {
                                refValue = this.getContext().object;
                            }
                            else
                            {
                                addResolveTask(new ResolveTask(parentContext, ref));
                                setResolveStatus(DefaultJSONParser.NeedToResolve);
                            }
                        }
                        else if ("$".equals(ref))
                        {
                            ParseContext rootContext = context;
                            while (rootContext.parent != null)
                            {
                                rootContext = rootContext.parent;
                            }

                            addResolveTask(new ResolveTask(rootContext, ref));
                            setResolveStatus(DefaultJSONParser.NeedToResolve);
                        }
                        else
                        {
                            addResolveTask(new ResolveTask(context, ref));
                            setResolveStatus(DefaultJSONParser.NeedToResolve);
                        }

                        if (lexer.token() != JSONToken.RBRACE)
                        {
                            throw new JSONException("syntax error");
                        }
                        lexer.nextToken(JSONToken.COMMA);

                        return unmodify(refValue);
                    }
                    else
                    {
                        throw new JSONException("illegal ref, " + JSONToken.name(lexer.token()));
                    }
                }

                if (!setContextFlag)
                {
                    setContext(object, fieldName);
                    setContextFlag = true;
                }

                Object value;
                if (ch == '"')
                {
                    lexer.scanString();
                    String strValue = lexer.stringVal();
                    value = strValue;

                    if (lexer.isEnabled(Feature.AllowISO8601DateFormat))
                    {
                        JSONScanner iso8601Lexer = new JSONScanner(strValue);
                        try
                        {
                            if (iso8601Lexer.scanISO8601DateIfMatch())
                            {
                                value = iso8601Lexer.getCalendar().getTime();
                            }
                        }
                        finally
                        {
                            iso8601Lexer.close();
                        }
                    }

                    if (object.getClass() == JSONObject.class)
                    {
                        setUnifyStringValue(object, key.toString(), value);
                    }
                    else
                    {
                        setUnifyStringValue(object, key, value);
                    }
                }
                else if (ch >= '0' && ch <= '9' || ch == '-')
                {
                    lexer.scanNumber();
                    if (lexer.token() == JSONToken.LITERAL_INT)
                    {
                        value = lexer.integerValue();
                    }
                    else
                    {
                        value = lexer.decimalValue();
                    }

                    setUnifyStringValue(object, key, value);
                }
                else if (ch == '[')
                { // 鍑忓皯娼滃锛屽吋瀹筧ndroid
                    lexer.nextToken();
                    List list = new ArrayList();
                    this.parseCollection(list, key);
                    value = list;
                    setUnifyStringValue(object, key, value);

                    if (lexer.token() == JSONToken.RBRACE)
                    {
                        lexer.nextToken();
                        return unmodify(object);
                    }
                    else if (lexer.token() == JSONToken.COMMA)
                    {
                        continue;
                    }
                    else
                    {
                        throw new JSONException("syntax error");
                    }
                }
                else if (ch == '{')
                { // 鍑忓皯娼滃锛屽吋瀹筧ndroid
                    lexer.nextToken();
                    Object obj = this.parseMap(new HashMap(), key);
                    checkMapResolve(object, key.toString());

                    if (object.getClass() == JSONObject.class)
                    {
                        setUnifyStringValue(object, key.toString(), obj);
                    }
                    else
                    {
                        setUnifyStringValue(object, key, obj);
                    }

                    setContext(context, obj, key);

                    if (lexer.token() == JSONToken.RBRACE)
                    {
                        lexer.nextToken();

                        setContext(context);
                        return unmodify(object);
                    }
                    else if (lexer.token() == JSONToken.COMMA)
                    {
                        continue;
                    }
                    else
                    {
                        throw new JSONException("syntax error, " + lexer.tokenName());
                    }
                }
                else
                {
                    lexer.nextToken();
                    value = parse();
                    setUnifyStringValue(object, key, value);

                    if (lexer.token() == JSONToken.RBRACE)
                    {
                        lexer.nextToken();
                        return unmodify(object);
                    }
                    else if (lexer.token() == JSONToken.COMMA)
                    {
                        continue;
                    }
                    else
                    {
                        throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
                    }
                }

                lexer.skipWhitespace();
                ch = lexer.getCurrent();
                if (ch == ',')
                {
                    lexer.next();
                    continue;
                }
                else if (ch == '}')
                {
                    lexer.next();
                    lexer.resetStringPosition();
                    lexer.nextToken();

                    this.setContext(object, fieldName);

                    return unmodify(object);
                }
                else
                {
                    throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
                }

            }
        }
        finally
        {
            this.setContext(context);
        }

    }

    private char onAllowAC(JSONScanner lexer, char ch)
    {
        if (isEnabled(Feature.AllowArbitraryCommas))
        {
            while (ch == ',')
            {
                lexer.next();
                lexer.skipWhitespace();
                ch = lexer.getCurrent();
            }
        }
        return ch;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void parseCollection(final Collection array, Object fieldName)
    {
        final JSONLexer lexer = getLexer();

        if (lexer.token() == JSONToken.SET || lexer.token() == JSONToken.TREE_SET)
        {
            lexer.nextToken();
        }

        if (lexer.token() != JSONToken.LBRACKET)
        {
            throw new JSONException("syntax error, expect [, actual " + JSONToken.name(lexer.token()));
        }

        lexer.nextToken(JSONToken.LITERAL_STRING);

        ParseContext context = this.getContext();
        this.setContext(array, fieldName);
        try
        {
            for (int i = 0;; ++i)
            {
                if (isEnabled(Feature.AllowArbitraryCommas))
                {
                    while (lexer.token() == JSONToken.COMMA)
                    {
                        lexer.nextToken();
                        continue;
                    }
                }

                Object value;
                switch (lexer.token())
                {
                case LITERAL_INT:
                    value = lexer.integerValue();
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                case LITERAL_FLOAT:
                    if (lexer.isEnabled(Feature.UseBigDecimal))
                    {
                        value = lexer.decimalValue(true);
                    }
                    else
                    {
                        value = lexer.decimalValue(false);
                    }
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                case LITERAL_STRING:
                    String stringLiteral = lexer.stringVal();
                    lexer.nextToken(JSONToken.COMMA);

                    if (lexer.isEnabled(Feature.AllowISO8601DateFormat))
                    {
                        JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
                        try
                        {
                            if (iso8601Lexer.scanISO8601DateIfMatch())
                            {
                                value = iso8601Lexer.getCalendar().getTime();
                            }
                            else
                            {
                                value = stringLiteral;
                            }
                        }
                        finally
                        {
                            iso8601Lexer.close();
                        }
                    }
                    else
                    {
                        value = stringLiteral;
                    }

                    break;
                case TRUE:
                    value = Boolean.TRUE;
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                case FALSE:
                    value = Boolean.FALSE;
                    lexer.nextToken(JSONToken.COMMA);
                    break;
                case LBRACE:
                    // JSONObject object = new JSONObject();
                    // value = parseObject(object, i);
                    Map map = new HashMap();
                    value = parseMap(map, i);
                    break;
                case LBRACKET:
                    // Collection items = new JSONArray();
                    // parseArray(items, i);
                    // value = items;
                    List collection = new ArrayList();
                    parseCollection(collection, i);
                    value = unmodify(collection);
                    break;
                case NULL:
                    value = null;
                    lexer.nextToken(JSONToken.LITERAL_STRING);
                    break;
                case RBRACKET:
                    lexer.nextToken(JSONToken.COMMA);
                    return;
                default:
                    value = parse();
                    break;
                }

                // array.add(value);
                array.add(getUnifyRef(value));
                checkListResolve(array);

                if (lexer.token() == JSONToken.COMMA)
                {
                    lexer.nextToken(JSONToken.LITERAL_STRING);
                    continue;
                }
            }
        }
        finally
        {
            this.setContext(context);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void setUnifyStringValue(Map obj, Object key, Object value)
    {
        obj.put(getUnifyRef(key), getUnifyRef(value));
    }

    /**

* 转换String对象引用地址,所有值相同的String对象都转换到统一的引用地址以节省内存
* 
* @param key
* @return
* /

    private Object getUnifyRef(Object key)
    {
        if (key == null)
        {
            return null;
        }

        if (!(key instanceof String))
        {
            return key;
        }

        String str = (String) key;

        String value = allCacheStr.get(str);
        if (value != null)
        {
            return value;
        }

        // 因为原来的输入参数key引用了包含整个缓存文件的char数组,
        // 如果不重新创建一个String对象而使用输入参数key,会导致char数组
        // 一直被引用而不能释放。
        // 解决办法是通过数组复制创建一个新String对象
        char[] c = new char[str.length()];
        str.getChars(0, str.length(), c, 0);
        str = new String(c);
        allCacheStr.put(str, str);
        return str;
    }

    /**

* 固化缓存内容使其不可修改
* 
* @author z00197812
* @createDate 2012-11-20
* @param obj
* @return
* /

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private Object unmodify(Object obj)
    {
        // if (obj instanceof Map)
        // {
        // return Collections.unmodifiableMap((Map) obj);
        // }
        //
        // if (obj instanceof List)
        // {
        // return Collections.unmodifiableList((List) obj);
        // }

        return obj;
    }
gajydyqb

gajydyqb3#

@wenshao
MapDeserializer 这个类就是fastjson 1.2.29 里面的源码

原因是是这样: 我jar 从fastjson 1.2.7 升级到了1.2.29
我们之前重写了上面的那个类 但是里面的代码还是基于之前1.2.7版本的, 我只是改了下对应的语法报错。

不知道是不是版本代码不兼容~

t30tvxxf

t30tvxxf4#

@wenshao 下面这个报错 是不是也是我们使用的源码也得基于最新版本的来写 ,是不是版本上代码不兼容,
我们使用的方式 1\使用jar , 2、 同时也重写了里面的类

com.alibaba.fastjson.JSONException: autoType is not support. com.huawei.appmarket.cachesys.Utils.CacheValue
at com.alibaba.fastjson.parser.ParserConfig.checkAutoType(ParserConfig.java:869) ~[fastjson-1.2.29.jar:?]
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:325) ~[fastjson-1.2.29.jar:?]
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1335) ~[fastjson-1.2.29.jar:?]
at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1301) ~[fastjson-1.2.29.jar:?]
at com.alibaba.fastjson.JSON.parse(JSON.java:148) ~[fastjson-1.2.29.jar:?]
at com.alibaba.fastjson.JSON.parse(JSON.java:139) ~[fastjson-1.2.29.jar:?]

---- 这个貌似这样就能解决。 https://github.com/alibaba/fastjson/wiki/enable_autotype

kwvwclae

kwvwclae5#

能否把需求直接提过来,而不是修改源码实现,修改源码我不好做兼容,每次改动不会考虑你的需求的,没有回归测试,就没有保证。

相关问题