Fastjson以前のバージョン1.2のバグ、自動仕分けデシリアライゼーションの、署名につながるが、

:みなさん、こんにちは、私はアヒルだ
、今日の問題を共有しますが、fastjsonの使用は、署名につながりました。

1.問題を再現:


fastjson 1.2.4
取得戻り値:

{"data":[{"id":"120190422110857284042111114","bankAccountType":"DEBIT","isMainCard":"0","bindId":"120190422110857284042111114","bankCardPhone":"15010311111","realName":null,"partBankAccountNo":"1199","bindChannel":"11111_PROTOCOL","masterAccountNo":null,"branchBankName":"建设银行","bankCode":"CCB"}],"sign":"nIBnR5YpoiYg4CwYIs5l1K2ne30X7A55YtjJH9teHYcZkRcPcI/ECg/TzKiMCFtKssOk1F8hXjC3Of2NhgYcduZAw4VjBb4HMuz9qRgSlZht0CXsMh8RVyysbJcKe8zhd4mansWzlxnIK2Kh3YnKf9Hzd/cHlcczr6UnDeifbZk="}

戻り値の配列を取得します:
 

[{"bankCode":"CCB","bankAccountType":"DEBIT","branchBankName":"建设银行","partBankAccountNo":"1199","id":"120190422110857284042111114","bindChannel":"11111_PROTOCOL","isMainCard":"0","bindId":"120190422110857284042111114","bankCardPhone":"15010311111"}]

fastjson 1.1.32
取得戻り値:

{"data":[{"id":"120190422110857284042111114","bankAccountType":"DEBIT","isMainCard":"0","bindId":"120190422110857284042111114","bankCardPhone":"15010311111","realName":null,"partBankAccountNo":"1199","bindChannel":"11111_PROTOCOL","masterAccountNo":null,"branchBankName":"建设银行","bankCode":"CCB"}],"sign":"nIBnR5YpoiYg4CwYIs5l1K2ne30X7A55YtjJH9teHYcZkRcPcI/ECg/TzKiMCFtKssOk1F8hXjC3Of2NhgYcduZAw4VjBb4HMuz9qRgSlZht0CXsMh8RVyysbJcKe8zhd4mansWzlxnIK2Kh3YnKf9Hzd/cHlcczr6UnDeifbZk="}

戻り値の配列を取得します:

[{"bankAccountType":"DEBIT","bankCardPhone":"15010311111","bankCode":"CCB","bindChannel":"11111_PROTOCOL","bindId":"120190422110857284042111114","branchBankName":"建设银行","id":"120190422110857284042111114","isMainCard":"0","partBankAccountNo":"1199"}]

署名された場合、サードパーティのJARパッケージの導入以来、戻り値はエラーをテストします。使用サードパーティ製の瓶のFastjsonバージョンは1.1.32ですが、私たちは、プロジェクトで使用1.2.4です。
あなたは、配列データの後に撮影した別のポイントを見ることができます。これは、アルファベット順の昇順で、(順番に配置された)自然順序付けに基づいています。本当にピットです....

2.ソースの分析:

固定JSON 1.2.4 

com.alibaba.fastjson.serializer.ListSerializerの
コードより簡潔、及び選別の配列を除去します

public final void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                                                                                                       throws IOException {

        boolean writeClassName = serializer.isEnabled(SerializerFeature.WriteClassName);

        SerializeWriter out = serializer.getWriter();

        Type elementType = null;
        if (writeClassName) {
            if (fieldType instanceof ParameterizedType) {
                ParameterizedType param = (ParameterizedType) fieldType;
                elementType = param.getActualTypeArguments()[0];
            }
        }

        if (object == null) {
            if (out.isEnabled(SerializerFeature.WriteNullListAsEmpty)) {
                out.write("[]");
            } else {
                out.writeNull();
            }
            return;
        }

        List<?> list = (List<?>) object;

        if (list.size() == 0) {
            out.append("[]");
            return;
        }

        SerialContext context = serializer.getContext();
        serializer.setContext(context, object, fieldName, 0);

        ObjectSerializer itemSerializer = null;
        try {
            if (out.isEnabled(SerializerFeature.PrettyFormat)) {
                out.append('[');
                serializer.incrementIndent();

                int i = 0;
                for (Object item : list) {
                    if (i != 0) {
                        out.append(',');
                    }

                    serializer.println();
                    if (item != null) {
                        if (serializer.containsReference(item)) {
                            serializer.writeReference(item);
                        } else {
                            itemSerializer = serializer.getObjectWriter(item.getClass());
                            SerialContext itemContext = new SerialContext(context, object, fieldName, 0, 0);
                            serializer.setContext(itemContext);
                            itemSerializer.write(serializer, item, i, elementType, 0);
                        }
                    } else {
                        serializer.getWriter().writeNull();
                    }
                    i++;
                }

                serializer.decrementIdent();
                serializer.println();
                out.append(']');
                return;
            }

            out.append('[');
            int i = 0;
            for (Object item : list) {
                if (i != 0) {
                    out.append(',');
                }
                
                if (item == null) {
                    out.append("null");
                } else {
                    Class<?> clazz = item.getClass();

                    if (clazz == Integer.class) {
                        out.writeInt(((Integer) item).intValue());
                    } else if (clazz == Long.class) {
                        long val = ((Long) item).longValue();
                        if (writeClassName) {
                            out.writeLongAndChar(val, 'L');
                        } else {
                            out.writeLong(val);
                        }
                    } else {
                        SerialContext itemContext = new SerialContext(context, object, fieldName, 0, 0);
                        serializer.setContext(itemContext);

                        if (serializer.containsReference(item)) {
                            serializer.writeReference(item);
                        } else {
                            itemSerializer = serializer.getObjectWriter(item.getClass());
                            itemSerializer.write(serializer, item, i, elementType, 0);
                        }
                    }
                }
                i++;
            }
            out.append(']');
        } finally {
            serializer.setContext(context);
        }
    }

fastjson 1.1.32
StringDeserializer

public static <T> T deserialze(DefaultJSONParser parser) {
    final JSONLexer lexer = parser.getLexer();
    if (lexer.token() == JSONToken.LITERAL_STRING) {
        String val = lexer.stringVal();
        lexer.nextToken(JSONToken.COMMA);
        return (T) val;
    }
    
    if (lexer.token() == JSONToken.LITERAL_INT) {
        String val = lexer.numberString();
        lexer.nextToken(JSONToken.COMMA);
        return (T) val;
    }

    Object value = parser.parse();

    if (value == null) {
        return null;
    }

    return (T) value.toString();
}

 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:
            JSONArray array = new JSONArray();
            parseArray(array, fieldName);
            return array;
        case LBRACE:
            JSONObject object = new JSONObject();
            return parseObject(object, 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:
            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;
        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, pos " + lexer.getBufferPosition());
        case ERROR:
        default:
            throw new JSONException("syntax error, pos " + lexer.getBufferPosition());
    }
}

焦点を当てます:

case LBRACKET:
            JSONArray array = new JSONArray();
            parseArray(array, fieldName);
            return array;

DefaultJSONParser:

public final void parseArray(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()) + ", pos "
                                + lexer.pos());
    }

    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);
                        if (iso8601Lexer.scanISO8601DateIfMatch()) {
                            value = iso8601Lexer.getCalendar().getTime();
                        } else {
                            value = stringLiteral;
                        }
                        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);
                    break;
                case LBRACKET:
                    Collection items = new JSONArray();
                    parseArray(items, i);
                    value = items;
                    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);
            checkListResolve(array);

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

com.alibaba.fastjson.serializer.SerializeWriter

writeStringWithDoubleQuote()並べ替え

 System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
            buf[lastSpecialIndex] = '\\';
            buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];

要約:


以来、デシリアライゼーション時fastjsonバージョン1.1.32、自動的にソート場合は1.2.4以降のバージョンが自動的に並べ替え、していないのJSONの暗号化と復号化バージョンが同じではありません、それがされます、エラーの暗号化と復号化につながります。
アリはfastjsonを見つけるために倉庫に行ってきました、以前のバージョン1.2.4は、説明の以前のバージョンは確かに問題はありません発見しました。

公開された115元の記事 ウォン称賛58 ビュー23万+

おすすめ

転載: blog.csdn.net/Angry_Mills/article/details/97651075