Skip to content

Commit

Permalink
Merge branch '2.15' into 2.16
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed May 3, 2023
2 parents 5b47599 + b8a22db commit 26466cb
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 6 deletions.
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ No changes since 2.15

#3894: Only avoid Records fields detection for deserialization
(contributed by Sim Y-T)
#3913: Issue with deserialization when there are unexpected properties (due
to null `StreamReadConstraints`)
(reported by @sbertault)

2.15.0 (23-Apr-2023)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri

// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(p, ctxt, bean, unknown);
return handlePolymorphic(p, ctxt, p.streamReadConstraints(), bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
Expand Down Expand Up @@ -538,7 +538,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) { // lgtm [java/dereferenced-value-may-be-null]
return handlePolymorphic(null, ctxt, bean, unknown);
return handlePolymorphic(null, ctxt, p.streamReadConstraints(), bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1735,18 +1735,41 @@ protected void handleIgnoredProperty(JsonParser p, DeserializationContext ctxt,
* @param p (optional) If not null, parser that has more properties to handle
* (in addition to buffered properties); if null, all properties are passed
* in buffer
* @deprecated use {@link #handlePolymorphic(JsonParser, DeserializationContext, StreamReadConstraints, Object, TokenBuffer)}
*/
@Deprecated
protected Object handlePolymorphic(JsonParser p, DeserializationContext ctxt,
Object bean, TokenBuffer unknownTokens)
throws IOException
{
final StreamReadConstraints streamReadConstraints = p == null ?
StreamReadConstraints.defaults() : p.streamReadConstraints();
return handlePolymorphic(p, ctxt, streamReadConstraints, bean, unknownTokens);
}

/**
* Method called in cases where we may have polymorphic deserialization
* case: that is, type of Creator-constructed bean is not the type
* of deserializer itself. It should be a sub-class or implementation
* class; either way, we may have more specific deserializer to use
* for handling it.
*
* @param p (optional) If not null, parser that has more properties to handle
* (in addition to buffered properties); if null, all properties are passed
* in buffer
* @since 2.15.1
*/
protected Object handlePolymorphic(JsonParser p, DeserializationContext ctxt,
StreamReadConstraints streamReadConstraints, Object bean, TokenBuffer unknownTokens)
throws IOException
{
// First things first: maybe there is a more specific deserializer available?
JsonDeserializer<Object> subDeser = _findSubclassDeserializer(ctxt, bean, unknownTokens);
if (subDeser != null) {
if (unknownTokens != null) {
// need to add END_OBJECT marker first
unknownTokens.writeEndObject();
JsonParser p2 = unknownTokens.asParser(p.streamReadConstraints());
JsonParser p2 = unknownTokens.asParser(streamReadConstraints);
p2.nextToken(); // to get to first data field
bean = subDeser.deserialize(p2, ctxt, bean);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p,
}
// polymorphic?
if (builder.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(p, ctxt, builder, unknown);
return handlePolymorphic(p, ctxt, p.streamReadConstraints(), builder, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
builder = handleUnknownProperties(ctxt, builder, unknown);
Expand Down Expand Up @@ -440,7 +440,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p,
if (unknown != null) {
// polymorphic?
if (builder.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, builder, unknown);
return handlePolymorphic(null, ctxt, p.streamReadConstraints(), builder, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, builder, unknown);
Expand Down Expand Up @@ -669,7 +669,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p,
continue; // never gets here
}
if (builder.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(p, ctxt, builder, tokens);
return handlePolymorphic(p, ctxt, p.streamReadConstraints(), builder, tokens);
}
return deserializeWithUnwrapped(p, ctxt, builder, tokens);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.fasterxml.jackson.databind.deser;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;

public class Issue3913DeserTest extends BaseMapTest
{
// [databind#3913]
static class MyResponse {
List<Base> list;

public List<Base> getList() {
return list;
}

public void setList(List<Base> list) {
this.list = list;
}
}

interface Base {

String getType();

String getMissingInJson();

@JsonCreator
static Base unmarshall(
@JsonProperty("missingInJson") String missingInJson,
@JsonProperty("type") String type
) {
switch (type) {
case "impl":
return new Impl(type, missingInJson);
default:
return null;
}
}
}

final static class Impl implements Base {
private String type;
private String missingInJson;

public Impl() {
}

public Impl(String type, String missingInJson) {
this.type = type;
this.missingInJson = missingInJson;
}

@Override public String getType() {
return type;
}

@Override public String getMissingInJson() {
return missingInJson;
}

public void setType(String type) {
this.type = type;
}

public void setMissingInJson(String missingInJson) {
this.missingInJson = missingInJson;
}
}

// [databind#3913]
public void testDeserialization() throws JsonProcessingException {
ObjectMapper mapper = jsonMapperBuilder()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build();
String rawResponse = "{\"list\":[{\"type\":\"impl\",\"unmappedKey\":\"unusedValue\"}]}";
MyResponse myResponse = mapper.readValue(rawResponse, MyResponse.class);
assertNotNull(myResponse);
assertEquals(1, myResponse.list.size());
assertEquals("impl", myResponse.list.get(0).getType());
assertNull(myResponse.list.get(0).getMissingInJson());
}
}

0 comments on commit 26466cb

Please sign in to comment.