Skip to content

Commit

Permalink
Merge branch 'master' into tatu/3.0/1484-mapper-feat-default-view-inc…
Browse files Browse the repository at this point in the history
…l-to-false
  • Loading branch information
cowtowncoder authored Jan 15, 2025
2 parents 6fae7e8 + 552c1d5 commit dafa892
Show file tree
Hide file tree
Showing 21 changed files with 150 additions and 94 deletions.
17 changes: 12 additions & 5 deletions src/main/java/tools/jackson/databind/exc/InvalidNullException.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package tools.jackson.databind.exc;

import tools.jackson.core.JsonParser;

import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.PropertyName;
Expand All @@ -8,11 +10,9 @@
/**
* Exception thrown if a `null` value is being encountered for a property
* designed as "fail on null" property (see {@link com.fasterxml.jackson.annotation.JsonSetter}).
*
* @since 2.9
*/
public class InvalidNullException
extends MismatchedInputException // since 2.9
extends MismatchedInputException
{
private static final long serialVersionUID = 1L; // silly Eclipse, warnings

Expand All @@ -27,11 +27,18 @@ public class InvalidNullException
/**********************************************************
*/

/**
* @since 2.19
*/
protected InvalidNullException(JsonParser p, String msg, PropertyName pname) {
super(p, msg);
_propertyName = pname;
}

protected InvalidNullException(DeserializationContext ctxt, String msg,
PropertyName pname)
{
super(ctxt == null ? null : ctxt.getParser(), msg);
_propertyName = pname;
this(ctxt == null ? null : ctxt.getParser(), msg, pname);
}

public static InvalidNullException from(DeserializationContext ctxt,
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/tools/jackson/databind/ObjectReaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ public void testUnknownFields() throws Exception
ObjectMapper mapper = JsonMapper.builder().addHandler(new DeserializationProblemHandler(){
@Override
public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, ValueDeserializer<?> deserializer, Object beanOrClass, String propertyName) {
p.readValueAsTree();
ctxt.readTree(p);
return true;
}
}).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public DataA deserialize(JsonParser p, DeserializationContext ctxt)
+p.currentToken());
// never gets here
}
/*JsonNode node =*/ p.readValueAsTree();
/*JsonNode node =*/ ctxt.readTree(p);

DataA da = new DataA();
da.i = 5;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ public void testCustomDeserializerWithReadTreeAsValue() throws Exception
assertEquals(new Point(13, -4), result.point);

// also, try some edge conditions
result = MAPPER.readValue(a2q("{'name':4})"), NamedPoint.class);
result = MAPPER.readValue(a2q("{'name':4}"), NamedPoint.class);
assertNotNull(result);
assertEquals("4", result.name);
assertNull(result.point);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public Bean deserialize(JsonParser p, DeserializationContext ctxt)
ctxt.reportInputMismatch(Bean.class,
"Deserializer not yet completely resolved");
}
p.skipChildren(); // consume the value
Bean b = new Bean();
b.value = 13;
return b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,25 @@ public void testJavaType() throws Exception
public void testTokenBufferWithSample() throws Exception
{
// First, try standard sample doc:
TokenBuffer result = MAPPER.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class);
verifyJsonSpecSampleDoc(result.asParser(ObjectReadContext.empty()), true);
result.close();
try (TokenBuffer result = MAPPER.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class)) {
verifyJsonSpecSampleDoc(result.asParser(ObjectReadContext.empty()), true);
}
}

@SuppressWarnings("resource")
@Test
public void testTokenBufferWithSequence() throws Exception
{
final ObjectMapper mapper = jsonMapperBuilder()
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build();

// and then sequence of other things
JsonParser p = MAPPER.createParser("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]");
JsonParser p = mapper.createParser("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]");
assertToken(JsonToken.START_ARRAY, p.nextToken());

assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
TokenBuffer buf = MAPPER.readValue(p, TokenBuffer.class);
TokenBuffer buf = mapper.readValue(p, TokenBuffer.class);

// check manually...
JsonParser bufParser = buf.asParser(ObjectReadContext.empty());
Expand All @@ -101,7 +105,7 @@ public void testTokenBufferWithSequence() throws Exception
assertNull(bufParser.nextToken());

// then bind to another
buf = MAPPER.readValue(p, TokenBuffer.class);
buf = mapper.readValue(p, TokenBuffer.class);
bufParser = buf.asParser(ObjectReadContext.empty());
assertToken(JsonToken.START_ARRAY, bufParser.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken());
Expand All @@ -110,13 +114,13 @@ public void testTokenBufferWithSequence() throws Exception
assertNull(bufParser.nextToken());

// third one, with automatic binding
buf = MAPPER.readValue(p, TokenBuffer.class);
String str = MAPPER.readValue(buf.asParser(ObjectReadContext.empty()), String.class);
buf = mapper.readValue(p, TokenBuffer.class);
String str = mapper.readValue(buf.asParser(ObjectReadContext.empty()), String.class);
assertEquals("abc", str);

// and ditto for last one
buf = MAPPER.readValue(p, TokenBuffer.class);
Map<?,?> map = MAPPER.readValue(buf.asParser(ObjectReadContext.empty()), Map.class);
buf = mapper.readValue(p, TokenBuffer.class);
Map<?,?> map = mapper.readValue(buf.asParser(ObjectReadContext.empty()), Map.class);
assertEquals(1, map.size());
assertEquals(Boolean.TRUE, map.get("a"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ public class SetterlessPropertiesDeserTest
{
static class CollectionBean
{
List<String> _values = new ArrayList<String>();
List<String> _values = new ArrayList<>();

public List<String> getValues() { return _values; }
}

static class MapBean
{
Map<String,Integer> _values = new HashMap<String,Integer>();
Map<String,Integer> _values = new HashMap<>();

public Map<String,Integer> getValues() { return _values; }
}

// testing to verify that field has precedence over getter, for lists
static class Dual
{
@JsonProperty("list") protected List<Integer> values = new ArrayList<Integer>();
@JsonProperty("list") protected List<Integer> values = new ArrayList<>();

public Dual() { }

Expand Down Expand Up @@ -129,7 +129,7 @@ public void testSetterlessPrecedence() throws Exception
ObjectMapper m = jsonMapperBuilder()
.enable(MapperFeature.USE_GETTERS_AS_SETTERS)
.build();
Dual value = m.readValue("{\"list\":[1,2,3]}, valueType)", Dual.class);
Dual value = m.readValue("{\"list\":[1,2,3]}", Dual.class);
assertNotNull(value);
assertEquals(3, value.values.size());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ public BogusBeanDeserializer(String a, String b) {
}

@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt)
public Object deserialize(JsonParser p, DeserializationContext ctxt)
{
p.skipChildren();
return new Bean(a, b);
}
}
Expand Down Expand Up @@ -168,7 +169,9 @@ public Issue1912SubBean(String a) {
}
}

public static class Issue1912CustomBeanDeserializer extends ValueDeserializer<Issue1912Bean> {
public static class Issue1912CustomBeanDeserializer
extends ValueDeserializer<Issue1912Bean>
{
private BeanDeserializer defaultDeserializer;

public Issue1912CustomBeanDeserializer(BeanDeserializer defaultDeserializer) {
Expand All @@ -178,16 +181,26 @@ public Issue1912CustomBeanDeserializer(BeanDeserializer defaultDeserializer) {
@Override
public Issue1912Bean deserialize(JsonParser p, DeserializationContext ctxt)
{
// this is need on some cases, this populate _propertyBasedCreator
defaultDeserializer.resolve(ctxt);

p.nextName(); // read subBean
p.nextToken(); // read start object
if (p.nextToken() != JsonToken.START_OBJECT) {
throw new IllegalArgumentException("Unexpected token "+p.currentToken());
}

Issue1912SubBean subBean = (Issue1912SubBean) defaultDeserializer.findProperty("subBean").deserialize(p, ctxt);
// Must also read trailing END_OBJECT
if (p.nextToken() != JsonToken.END_OBJECT) {
throw new IllegalArgumentException("Unexpected token "+p.currentToken());
}

return new Issue1912Bean(subBean);
}

@Override
public ValueDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
{
return new Issue1912CustomBeanDeserializer(
(BeanDeserializer) defaultDeserializer.createContextual(ctxt, property));
}
}

public static class Issue1912CustomPropertyDeserializer extends ValueDeserializer<Issue1912SubBean>
Expand Down Expand Up @@ -247,8 +260,9 @@ static class ArrayDeserializerModifier extends ValueDeserializerModifier {
public ValueDeserializer<?> modifyArrayDeserializer(DeserializationConfig config, ArrayType valueType,
BeanDescription beanDesc, ValueDeserializer<?> deserializer) {
return (ValueDeserializer<?>) new StdDeserializer<Object>(Object.class) {
@Override public Object deserialize(JsonParser jp,
@Override public Object deserialize(JsonParser p,
DeserializationContext ctxt) {
p.skipChildren();
return new String[] { "foo" };
}
};
Expand All @@ -260,8 +274,9 @@ static class CollectionDeserializerModifier extends ValueDeserializerModifier {
public ValueDeserializer<?> modifyCollectionDeserializer(DeserializationConfig config, CollectionType valueType,
BeanDescription beanDesc, ValueDeserializer<?> deserializer) {
return (ValueDeserializer<?>) new StdDeserializer<Object>(Object.class) {
@Override public Object deserialize(JsonParser jp,
@Override public Object deserialize(JsonParser p,
DeserializationContext ctxt) {
p.skipChildren();
ArrayList<String> list = new ArrayList<String>();
list.add("foo");
return list;
Expand All @@ -275,8 +290,9 @@ static class MapDeserializerModifier extends ValueDeserializerModifier {
public ValueDeserializer<?> modifyMapDeserializer(DeserializationConfig config, MapType valueType,
BeanDescription beanDesc, ValueDeserializer<?> deserializer) {
return (ValueDeserializer<?>) new StdDeserializer<Object>(Object.class) {
@Override public Object deserialize(JsonParser jp,
@Override public Object deserialize(JsonParser p,
DeserializationContext ctxt) {
p.skipChildren();
HashMap<String,String> map = new HashMap<String,String>();
map.put("a", "foo");
return map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ public void testBuilderMethodReturnMoreSpecific() throws Exception
@Test
public void testSelfBuilder777() throws Exception
{
SelfBuilder777 result = MAPPER.readValue(a2q("{'x':3}'"),
SelfBuilder777 result = MAPPER.readValue(a2q("{'x':3}"),
SelfBuilder777.class);
assertNotNull(result);
assertEquals(3, result.x);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,16 @@ public void testSimple() throws Exception
{
// First "good" case with Strings
String JSON = "\"OK\" \"RULES\" null";
// multiple main-level mappings, need explicit parser:
JsonParser p = MAPPER.createParser(JSON);
// multiple main-level mappings, need explicit parser
// (and possibly prevent validation of trailing tokens)
ObjectMapper mapper = jsonMapperBuilder()
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build();

JsonParser p = mapper.createParser(JSON);

assertEquals(TestEnum.OK, MAPPER.readValue(p, TestEnum.class));
assertEquals(TestEnum.RULES, MAPPER.readValue(p, TestEnum.class));
assertEquals(TestEnum.OK, mapper.readValue(p, TestEnum.class));
assertEquals(TestEnum.RULES, mapper.readValue(p, TestEnum.class));

// should be ok; nulls are typeless; handled by mapper, not by deserializer
assertNull(MAPPER.readValue(p, TestEnum.class));
Expand All @@ -296,11 +301,11 @@ public void testSimple() throws Exception
assertFalse(p.hasCurrentToken());

// Then alternative with index (0 means first entry)
assertEquals(TestEnum.JACKSON, MAPPER.readValue(" 0 ", TestEnum.class));
assertEquals(TestEnum.JACKSON, mapper.readValue(" 0 ", TestEnum.class));

// Then error case: unrecognized value
try {
/*Object result =*/ MAPPER.readValue("\"NO-SUCH-VALUE\"", TestEnum.class);
/*Object result =*/ mapper.readValue("\"NO-SUCH-VALUE\"", TestEnum.class);
fail("Expected an exception for bogus enum value...");
} catch (MismatchedInputException jex) {
verifyException(jex, "not one of the values accepted for Enum class");
Expand All @@ -309,8 +314,8 @@ public void testSimple() throws Exception
}

/**
* Enums are considered complex if they have code (and hence sub-classes)... an
* example is TimeUnit
* Enums are considered complex if they have code (and hence sub-classes)...
* an example is TimeUnit
*/
@Test
public void testComplexEnum() throws Exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public Object handleUnexpectedToken(DeserializationContext ctxt,
JavaType targetType, JsonToken t, JsonParser p,
String failureMsg)
{
p.skipChildren();
return value;
}
}
Expand Down Expand Up @@ -368,6 +369,10 @@ public void testInstantiationExceptionHandling() throws Exception
public void testMissingInstantiatorHandling() throws Exception
{
ObjectMapper mapper = jsonMapperBuilder()
// 14-Jan-2025, tatu: Need to disable trailing tokens (for 3.0)
// for this to work (handler not consuming all tokens as it should
// but no time to fully fix right now)
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.addHandler(new MissingInstantiationHandler(new NoDefaultCtor(13)))
.build();
NoDefaultCtor w = mapper.readValue("{ \"x\" : true }", NoDefaultCtor.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
import tools.jackson.databind.*;
import tools.jackson.databind.exc.MismatchedInputException;
import tools.jackson.databind.util.ClassUtil;
import tools.jackson.databind.testutil.DatabindTestUtil;

import static org.junit.jupiter.api.Assertions.*;

import static tools.jackson.databind.testutil.DatabindTestUtil.*;

/**
* Unit tests for verifying handling of simple basic non-structured
* types; primitives (and/or their wrappers), Strings.
*/
public class JDKScalarsDeserTest
extends DatabindTestUtil
{
private final static String NAN_STRING = "NaN";

Expand Down Expand Up @@ -548,7 +548,7 @@ public void testBase64Variants() throws Exception

/**
* Then a unit test to verify that we can conveniently bind sequence of
* space-separate simple values
* space-separated simple values
*/
@Test
public void testSequenceOfInts() throws Exception
Expand All @@ -560,12 +560,15 @@ public void testSequenceOfInts() throws Exception
sb.append(" ");
sb.append(i);
}
JsonParser p = MAPPER.createParser(sb.toString());
for (int i = 0; i < NR_OF_INTS; ++i) {
Integer result = MAPPER.readValue(p, Integer.class);
assertEquals(Integer.valueOf(i), result);
ObjectMapper mapper = jsonMapperBuilder()
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.build();
try (JsonParser p = mapper.createParser(sb.toString())) {
for (int i = 0; i < NR_OF_INTS; ++i) {
Integer result = mapper.readValue(p, Integer.class);
assertEquals(Integer.valueOf(i), result);
}
}
p.close();
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,14 @@ public void testUUIDAux() throws Exception
byte[] data = bytes.toByteArray();
assertEquals(16, data.length);

buf.writePOJO(data);

UUID value2 = MAPPER.readValue(buf.asParser(ObjectReadContext.empty()), UUID.class);

assertEquals(value, value2);
buf.close();
// Let's create fresh TokenBuffer, not reuse one
try (TokenBuffer buf2 = TokenBuffer.forGeneration()) {
buf2.writePOJO(data);

UUID value2 = MAPPER.readValue(buf2.asParser(), UUID.class);

assertEquals(value, value2);
}
}
}
}
Loading

0 comments on commit dafa892

Please sign in to comment.