When deserializing a custom EnumMap subtype with a property-based
@JsonCreator and EnumFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL
enabled, encountering an unknown enum key corrupts the parser position.
Entries that follow the unknown key, including both creator properties
and regular map entries, are then no longer handled correctly.
The issue is in _deserializeUsingProperties(): the loop already calls
p.nextToken() to advance to the value, but the unknown-key skip branch
calls p.nextToken() a second time before p.skipChildren(). That
extra advance moves past the value, so skipChildren() operates on the
wrong token.
The regular deserialize() path in the same class handles this
correctly: it calls only p.skipChildren() without the preceding
nextToken().
To reproduce:
enum MyEnum { A, B, C }
static class MyEnumMap extends EnumMap<MyEnum, String> {
int x, y;
@JsonCreator
public MyEnumMap(@JsonProperty("x") int x, @JsonProperty("y") int y) {
super(MyEnum.class);
this.x = x;
this.y = y;
}
}
ObjectMapper mapper = JsonMapper.builder()
.enable(EnumFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.build();
MyEnumMap map = mapper.readValue(
"{\"x\":1, \"NOPE\":{\"nested\":true}, \"y\":2, \"A\":\"val\"}",
MyEnumMap.class);
// Expected: x=1, y=2, and A -> "val"
// Actual: properties after the unknown key are not handled correctly
Version: 3.1 branch HEAD
When deserializing a custom
EnumMapsubtype with a property-based@JsonCreatorandEnumFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULLenabled, encountering an unknown enum key corrupts the parser position.
Entries that follow the unknown key, including both creator properties
and regular map entries, are then no longer handled correctly.
The issue is in
_deserializeUsingProperties(): the loop already callsp.nextToken()to advance to the value, but the unknown-key skip branchcalls
p.nextToken()a second time beforep.skipChildren(). Thatextra advance moves past the value, so
skipChildren()operates on thewrong token.
The regular
deserialize()path in the same class handles thiscorrectly: it calls only
p.skipChildren()without the precedingnextToken().To reproduce:
Version: 3.1 branch HEAD