Skip to content

[BUG] Codegen incorrectly deserializes Maps because of double jsonReader.readFieldName() call #3833

@artpaym

Description

@artpaym

Description:
Codegen incorrectly deserializes Maps because of double jsonReader.readFieldName() call.

For example, if your DTO has "elements" Map field, the generated code in ..._FASTJSONReader looks like this (the relevant piece):

...
                                        String elements_key = jsonReader.readFieldName();
                                        if (jsonReader.isReference()) {
                                            String ref = jsonReader.readReference();
                                            jsonReader.addResolveTask(elements, elements_key, JSONPath.of(ref));
                                        } else {
                                            elements.put(jsonReader.readFieldName(), (MyDto)this.itemReader0.readObject(jsonReader, MyDto.class, "elements", features));
                                        }
...

So the flow is:

  1. String elements_key = jsonReader.readFieldName();
  2. elements.put(jsonReader.readFieldName(), ...
    causing the reader to advance multiple times on the field name hence breaking the reader cursor basically.

Seems like the cause is here:

exec(method(fieldValueVar, "put", mapEntryKeyExpr, mapEntryValueExpr))

Instead of mapEntryKeyExpr it should use ident(mapKey) to fix it, it seems.

It worked fine, when I copy pasted generated code with the fix applied on top, so it's likely the cause.

Environment:

  • OS: Linux
  • JDK: Openjdk-21.0.5+11
  • Fastjson2 and codegen: 2.0.59
  • Quarkus: 3.28.4

Reproduction:

  1. Use a Map field in your DTO class with codegen, for example:
@JSONCompiled
@JSONType
public class MyDto {
    ...
    public Map<String, MyOtherDto> elements;
    ...
  1. Build the project.
  2. Send some corresponding valid json.
  3. Parse json: MyDto dto = JSON.parseObject(json, MyDto.class);

Actual

Instead of real valid "elements" items, your MyDto will have only a single element with "null" key (though I suppose you might see a different result, because an incorrectly advanced parser might yield different results depending on input data, etc).

The real json had something like this instead:

...
    "elements": {
      ...
      "7": {
        "format": "mmddhhnnss",
        "id": 7,
        "type": "datetime",
        "value": "0302054257"
      },
      ...
    }
...

Expected

Map gets parsed correctly, and then written back to json string also correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions