:みなさん、こんにちは、私はアヒルだ
、今日の問題を共有しますが、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は、説明の以前のバージョンは確かに問題はありません発見しました。