alibaba / alibaba/fastjson2

[BUG] 数组、实体对象等非基本类型和String 作为Map.key时,开启AutoType,序列化后,反序列化报错

Open
#7,686 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
4.4k
Forks
613
Avg merge
1d 22h
Merged PRs (30d)
6

Description

### 问题描述
*简要描述您碰到的问题。*
数组、实体对象等非基本类型和String 作为Map.key时,开启AutoType,序列化后,如果未指定具体的目标类型,则反序列化报错
### 环境信息
*请填写以下信息:*

- OS信息: [e.g.:CentOS 8.4.2105 4Core 3.10GHz 16 GB]
- JDK信息: [e.g.:Openjdk 1.8.0_312]
- 版本信息:[e.g.:Fastjson2 2.0.61]

### 重现步骤
*如何操作可以重现该问题:*
```java
public void testEntityKeyEncode() {
Map map = new HashMap<>();
map.put(new TestKey(1), "value1");
map.put(new TestKey(2), "value2");
String jsonString = JSONUtil.encode(map);
System.out.println(jsonString);
Object jasonObject = JSONObject.parseObject(jsonString, Object.class, Feature.AllowUnQuotedFieldNames);

System.out.println(JSONObject.toJSONString(jasonObject));
Object object = JSONUtil.decode(jsonString, new com.alibaba.fastjson2.TypeReference>() {
});
String jsonString2 = JSONUtil.toJSONString(object);
System.out.println(jsonString2);

Object jasonObject3 = JSONUtil.decode(jsonString, Map.class);
String jsonString3 = JSONUtil.toJSONString(jasonObject3);
System.out.println(jsonString3);
}

public void testArrayKeyEncode() {
Map map = new HashMap<>();
map.put(new Integer[]{1, 2}, "value1");
map.put(new Integer[]{3, 4}, "value2");
String jsonString = JSONUtil.encode(map);
System.out.println(jsonString);
Object jasonObject = JSONObject.parseObject(jsonString, Object.class, Feature.AllowUnQuotedFieldNames);

System.out.println(JSONObject.toJSONString(jasonObject));
Object object = JSONUtil.decode(jsonString, new com.alibaba.fastjson2.TypeReference>() {
});
String jsonString2 = JSONUtil.toJSONString(object);
System.out.println(jsonString2);

Object jasonObject3 = JSONUtil.decode(jsonString, Map.class);
String jsonString3 = JSONUtil.toJSONString(jasonObject3);
System.out.println(jsonString3);
}

public static String encode(Object object) {
// 要避免String类型 再次被包装
if (object instanceof String) {
return (String) object;
}
return JSONObject.toJSONString(object
, Feature.WriteClassName
, Feature.IgnoreErrorGetter
, Feature.FieldBased
, Feature.WriteNonStringKeyAsString
);
}

public static T decode(String s, Class t) {
s = JediStrUtil.isEmpty(s) ? null : s;
return JSON.parseObject(s, t
, autoTypeBeforeHandler
, JSONReader.Feature.FieldBased
, JSONReader.Feature.IgnoreAutoTypeNotMatch
, JSONReader.Feature.UseNativeObject
, JSONReader.Feature.SupportClassForName
, JSONReader.Feature.AllowUnQuotedFieldNames
);
}

public static class TestKey {
int id;

public TestKey(int id) {
this.id = id;
}
}
```

### 期待的正确结果
*对您期望发生的结果进行清晰简洁的描述。*
能够根据ClassName 正确解析成指定的对象

### 相关日志输出
*请复制并粘贴任何相关的日志输出。*
```
{"@type":"java.util.HashMap",[3,4]:"value2",[1,2]:"value1"}
{"@type":"java.util.HashMap",[3,4]:"value2",[1,2]:"value1"}
{[1,2]:"value1",[3,4]:"value2"}

com.alibaba.fastjson2.JSONException: illegal input, offset 30, character [, line 1, column 30, fastjson-version 2.0.61 {"@type":"java.util.HashMap",[3,4]:"value2",[1,2]:"value1"}

at com.alibaba.fastjson2.JSONReader.readFieldNameUnquote(JSONReader.java:1697)
at com.alibaba.fastjson2.JSONReader.read(JSONReader.java:3485)
at com.alibaba.fastjson2.reader.ObjectReaderImplMap.readObject(ObjectReaderImplMap.java:453)
at com.alibaba.fastjson2.JSON.parseObject(JSON.java:1034)
at com.jedi.framework.utils.JSONUtil.decode(JSONUtil.java:183)
at com.jedi.framework.utils.JSONUtilTest.testArrayKeyEncode(JSONUtilTest.java:158)

{"@type":"java.util.HashMap",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":1}:"value1",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":2}:"value2"}
{"@type":"java.util.HashMap",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":1}:"value1",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":2}:"value2"}
{{"id":1}:"value1",{"id":2}:"value2"}

com.alibaba.fastjson2.JSONException: illegal input, offset 30, character {, line 1, column 30, fastjson-version 2.0.61 {"@type":"java.util.HashMap",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":1}:"value1",{"@type":"com.jedi.framework.utils.JSONUtilTest$TestKey","id":2}:"value2"}

at com.alibaba.fastjson2.JSONReader.readFieldNameUnquote(JSONReader.java:1697)
at com.alibaba.fastjson2.JSONReader.read(JSONReader.java:3485)
at com.alibaba.fastjson2.reader.ObjectReaderImplMap.readObject(ObjectReaderImplMap.java:453)
at com.alibaba.fastjson2.JSON.parseObject(JSON.java:1034)
at com.jedi.framework.utils.JSONUtil.decode(JSONUtil.java:183)
```

#### 附加信息
*如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。*

Contributor guide

Open the contributing guide

Research direction

Start with the failing testEntityKeyEncode and testArrayKeyEncode cases in JSONUtilTest, then trace the reported stack through JSON.parseObject, JSONReader.readFieldNameUnquote, and ObjectReaderImplMap.readObject. Reproduce the failures for array and entity-object map keys with AutoType enabled; done means both cases deserialize according to their ClassName without the reported illegal-input errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.