Skip to content

Commit

Permalink
Add fix along lines of #777, unit test for verifying
Browse files Browse the repository at this point in the history
cowtowncoder committed Jun 12, 2015
1 parent 3ef01e0 commit ad598aa
Showing 4 changed files with 55 additions and 23 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
@@ -49,6 +49,8 @@ Project: jackson-databind
#765: `SimpleType.withStaticTyping()` impl incorrect
#769: Fix `JacksonAnnotationIntrospector.findDeserializer` to return `Object` (as per
`AnnotationIntrospector`); similarly for other `findXxx(De)Serializer(...)` methods
#777: Allow missing build method if its name is empty ("")
(suggested by galdosd@github)
#781: Support handling of `@JsonProperty.required` for Creator methods
#787: Add `ObjectMapper setFilterProvider(FilterProvider)` to allow chaining
(suggested by rgoldberg@githin)
Original file line number Diff line number Diff line change
@@ -369,18 +369,22 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
{
// First: validation; must have build method that returns compatible type
if (_buildMethod == null) {
throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
+" does not have build method '"+expBuildMethodName+"()'");
}
// also: type of the method must be compatible
Class<?> rawBuildType = _buildMethod.getRawReturnType();
Class<?> rawValueType = valueType.getRawClass();
if ((rawBuildType != rawValueType)
&& !rawBuildType.isAssignableFrom(rawValueType)
&& !rawValueType.isAssignableFrom(rawBuildType)) {
throw new IllegalArgumentException("Build method '"+_buildMethod.getFullName()
+" has bad return type ("+rawBuildType.getName()
+"), not compatible with POJO type ("+valueType.getRawClass().getName()+")");
// as per [databind#777], allow empty name
if (!expBuildMethodName.isEmpty()) {
throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
+" does not have build method (name: '"+expBuildMethodName+"')");
}
} else {
// also: type of the method must be compatible
Class<?> rawBuildType = _buildMethod.getRawReturnType();
Class<?> rawValueType = valueType.getRawClass();
if ((rawBuildType != rawValueType)
&& !rawBuildType.isAssignableFrom(rawValueType)
&& !rawValueType.isAssignableFrom(rawBuildType)) {
throw new IllegalArgumentException("Build method '"+_buildMethod.getFullName()
+" has bad return type ("+rawBuildType.getName()
+"), not compatible with POJO type ("+valueType.getRawClass().getName()+")");
}
}
// And if so, we can try building the deserializer
Collection<SettableBeanProperty> props = _properties.values();
Original file line number Diff line number Diff line change
@@ -117,6 +117,10 @@ protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
protected final Object finishBuild(DeserializationContext ctxt, Object builder)
throws IOException
{
// As per [databind#777], allow returning builder itself
if (null == _buildMethod) {
return builder;
}
try {
return _buildMethod.getMember().invoke(builder);
} catch (Exception e) {
Original file line number Diff line number Diff line change
@@ -249,7 +249,19 @@ public ValueClassXY build() {
return null;
}
}


// [databind#777]
@JsonDeserialize(builder = SelfBuilder777.class)
@JsonPOJOBuilder(buildMethodName = "", withPrefix = "with")
static class SelfBuilder777 {
public int x;

public SelfBuilder777 withX(int value) {
x = value;
return this;
}
}

// [databind#822]
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "with")
static class ValueBuilder822
@@ -289,12 +301,12 @@ public ValueClass822(int x, Map<String,Object> stuff) {
/**********************************************************
*/

private final ObjectMapper mapper = new ObjectMapper();
private final ObjectMapper MAPPER = new ObjectMapper();

public void testSimple() throws Exception
{
String json = "{\"x\":1,\"y\":2}";
Object o = mapper.readValue(json, ValueClassXY.class);
Object o = MAPPER.readValue(json, ValueClassXY.class);
assertNotNull(o);
assertSame(ValueClassXY.class, o.getClass());
ValueClassXY value = (ValueClassXY) o;
@@ -306,7 +318,7 @@ public void testSimple() throws Exception
public void testMultiAccess() throws Exception
{
String json = "{\"c\":3,\"a\":2,\"b\":-9}";
ValueClassABC value = mapper.readValue(json, ValueClassABC.class);
ValueClassABC value = MAPPER.readValue(json, ValueClassABC.class);
assertNotNull(value);
// note: ctor adds one to both values
assertEquals(value.a, 2);
@@ -318,23 +330,23 @@ public void testMultiAccess() throws Exception
public void testImmutable() throws Exception
{
final String json = "{\"value\":13}";
ValueImmutable value = mapper.readValue(json, ValueImmutable.class);
ValueImmutable value = MAPPER.readValue(json, ValueImmutable.class);
assertEquals(13, value.value);
}

// test with custom 'with-prefix'
public void testCustomWith() throws Exception
{
final String json = "{\"value\":1}";
ValueFoo value = mapper.readValue(json, ValueFoo.class);
ValueFoo value = MAPPER.readValue(json, ValueFoo.class);
assertEquals(1, value.value);
}

// test to ensure @JsonCreator also work
public void testWithCreator() throws Exception
{
final String json = "{\"a\":1,\"c\":3,\"b\":2}";
CreatorValue value = mapper.readValue(json, CreatorValue.class);
CreatorValue value = MAPPER.readValue(json, CreatorValue.class);
assertEquals(1, value.a);
assertEquals(2, value.b);
assertEquals(3, value.c);
@@ -345,22 +357,22 @@ public void testWithCreator() throws Exception
public void testBuilderMethodReturnMoreGeneral() throws Exception
{
final String json = "{\"x\":1}";
ValueInterface value = mapper.readValue(json, ValueInterface.class);
ValueInterface value = MAPPER.readValue(json, ValueInterface.class);
assertEquals(2, value.getX());
}

public void testBuilderMethodReturnMoreSpecific() throws Exception
{
final String json = "{\"x\":1}";
ValueInterface2 value = mapper.readValue(json, ValueInterface2.class);
ValueInterface2 value = MAPPER.readValue(json, ValueInterface2.class);
assertEquals(2, value.getX());
}

public void testBuilderMethodReturnInvalidType() throws Exception
{
final String json = "{\"x\":1}";
try {
mapper.readValue(json, ValueClassWrongBuildType.class);
MAPPER.readValue(json, ValueClassWrongBuildType.class);
fail("Missing expected JsonProcessingException exception");
} catch(JsonProcessingException e) {
assertTrue(
@@ -369,10 +381,18 @@ public void testBuilderMethodReturnInvalidType() throws Exception
}
}

public void testSelfBuilder777() throws Exception
{
SelfBuilder777 result = MAPPER.readValue(aposToQuotes("{'x':3}'"),
SelfBuilder777.class);
assertNotNull(result);
assertEquals(3, result.x);
}

public void testWithAnySetter822() throws Exception
{
final String json = "{\"extra\":3,\"foobar\":[ ],\"x\":1,\"name\":\"bob\"}";
ValueClass822 value = mapper.readValue(json, ValueClass822.class);
ValueClass822 value = MAPPER.readValue(json, ValueClass822.class);
assertEquals(1, value.x);
assertNotNull(value.stuff);
assertEquals(3, value.stuff.size());
@@ -383,4 +403,6 @@ public void testWithAnySetter822() throws Exception
assertTrue(ob instanceof List);
assertTrue(((List<?>) ob).isEmpty());
}


}

0 comments on commit ad598aa

Please sign in to comment.