Skip to content

Commit ad598aa

Browse files
committed
Add fix along lines of #777, unit test for verifying
1 parent 3ef01e0 commit ad598aa

File tree

4 files changed

+55
-23
lines changed

4 files changed

+55
-23
lines changed

release-notes/VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Project: jackson-databind
4949
#765: `SimpleType.withStaticTyping()` impl incorrect
5050
#769: Fix `JacksonAnnotationIntrospector.findDeserializer` to return `Object` (as per
5151
`AnnotationIntrospector`); similarly for other `findXxx(De)Serializer(...)` methods
52+
#777: Allow missing build method if its name is empty ("")
53+
(suggested by galdosd@github)
5254
#781: Support handling of `@JsonProperty.required` for Creator methods
5355
#787: Add `ObjectMapper setFilterProvider(FilterProvider)` to allow chaining
5456
(suggested by rgoldberg@githin)

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -369,18 +369,22 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
369369
{
370370
// First: validation; must have build method that returns compatible type
371371
if (_buildMethod == null) {
372-
throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
373-
+" does not have build method '"+expBuildMethodName+"()'");
374-
}
375-
// also: type of the method must be compatible
376-
Class<?> rawBuildType = _buildMethod.getRawReturnType();
377-
Class<?> rawValueType = valueType.getRawClass();
378-
if ((rawBuildType != rawValueType)
379-
&& !rawBuildType.isAssignableFrom(rawValueType)
380-
&& !rawValueType.isAssignableFrom(rawBuildType)) {
381-
throw new IllegalArgumentException("Build method '"+_buildMethod.getFullName()
382-
+" has bad return type ("+rawBuildType.getName()
383-
+"), not compatible with POJO type ("+valueType.getRawClass().getName()+")");
372+
// as per [databind#777], allow empty name
373+
if (!expBuildMethodName.isEmpty()) {
374+
throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
375+
+" does not have build method (name: '"+expBuildMethodName+"')");
376+
}
377+
} else {
378+
// also: type of the method must be compatible
379+
Class<?> rawBuildType = _buildMethod.getRawReturnType();
380+
Class<?> rawValueType = valueType.getRawClass();
381+
if ((rawBuildType != rawValueType)
382+
&& !rawBuildType.isAssignableFrom(rawValueType)
383+
&& !rawValueType.isAssignableFrom(rawBuildType)) {
384+
throw new IllegalArgumentException("Build method '"+_buildMethod.getFullName()
385+
+" has bad return type ("+rawBuildType.getName()
386+
+"), not compatible with POJO type ("+valueType.getRawClass().getName()+")");
387+
}
384388
}
385389
// And if so, we can try building the deserializer
386390
Collection<SettableBeanProperty> props = _properties.values();

src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ protected BeanAsArrayBuilderDeserializer asArrayDeserializer() {
117117
protected final Object finishBuild(DeserializationContext ctxt, Object builder)
118118
throws IOException
119119
{
120+
// As per [databind#777], allow returning builder itself
121+
if (null == _buildMethod) {
122+
return builder;
123+
}
120124
try {
121125
return _buildMethod.getMember().invoke(builder);
122126
} catch (Exception e) {

src/test/java/com/fasterxml/jackson/databind/creators/BuilderSimpleTest.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,19 @@ public ValueClassXY build() {
249249
return null;
250250
}
251251
}
252-
252+
253+
// [databind#777]
254+
@JsonDeserialize(builder = SelfBuilder777.class)
255+
@JsonPOJOBuilder(buildMethodName = "", withPrefix = "with")
256+
static class SelfBuilder777 {
257+
public int x;
258+
259+
public SelfBuilder777 withX(int value) {
260+
x = value;
261+
return this;
262+
}
263+
}
264+
253265
// [databind#822]
254266
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "with")
255267
static class ValueBuilder822
@@ -289,12 +301,12 @@ public ValueClass822(int x, Map<String,Object> stuff) {
289301
/**********************************************************
290302
*/
291303

292-
private final ObjectMapper mapper = new ObjectMapper();
304+
private final ObjectMapper MAPPER = new ObjectMapper();
293305

294306
public void testSimple() throws Exception
295307
{
296308
String json = "{\"x\":1,\"y\":2}";
297-
Object o = mapper.readValue(json, ValueClassXY.class);
309+
Object o = MAPPER.readValue(json, ValueClassXY.class);
298310
assertNotNull(o);
299311
assertSame(ValueClassXY.class, o.getClass());
300312
ValueClassXY value = (ValueClassXY) o;
@@ -306,7 +318,7 @@ public void testSimple() throws Exception
306318
public void testMultiAccess() throws Exception
307319
{
308320
String json = "{\"c\":3,\"a\":2,\"b\":-9}";
309-
ValueClassABC value = mapper.readValue(json, ValueClassABC.class);
321+
ValueClassABC value = MAPPER.readValue(json, ValueClassABC.class);
310322
assertNotNull(value);
311323
// note: ctor adds one to both values
312324
assertEquals(value.a, 2);
@@ -318,23 +330,23 @@ public void testMultiAccess() throws Exception
318330
public void testImmutable() throws Exception
319331
{
320332
final String json = "{\"value\":13}";
321-
ValueImmutable value = mapper.readValue(json, ValueImmutable.class);
333+
ValueImmutable value = MAPPER.readValue(json, ValueImmutable.class);
322334
assertEquals(13, value.value);
323335
}
324336

325337
// test with custom 'with-prefix'
326338
public void testCustomWith() throws Exception
327339
{
328340
final String json = "{\"value\":1}";
329-
ValueFoo value = mapper.readValue(json, ValueFoo.class);
341+
ValueFoo value = MAPPER.readValue(json, ValueFoo.class);
330342
assertEquals(1, value.value);
331343
}
332344

333345
// test to ensure @JsonCreator also work
334346
public void testWithCreator() throws Exception
335347
{
336348
final String json = "{\"a\":1,\"c\":3,\"b\":2}";
337-
CreatorValue value = mapper.readValue(json, CreatorValue.class);
349+
CreatorValue value = MAPPER.readValue(json, CreatorValue.class);
338350
assertEquals(1, value.a);
339351
assertEquals(2, value.b);
340352
assertEquals(3, value.c);
@@ -345,22 +357,22 @@ public void testWithCreator() throws Exception
345357
public void testBuilderMethodReturnMoreGeneral() throws Exception
346358
{
347359
final String json = "{\"x\":1}";
348-
ValueInterface value = mapper.readValue(json, ValueInterface.class);
360+
ValueInterface value = MAPPER.readValue(json, ValueInterface.class);
349361
assertEquals(2, value.getX());
350362
}
351363

352364
public void testBuilderMethodReturnMoreSpecific() throws Exception
353365
{
354366
final String json = "{\"x\":1}";
355-
ValueInterface2 value = mapper.readValue(json, ValueInterface2.class);
367+
ValueInterface2 value = MAPPER.readValue(json, ValueInterface2.class);
356368
assertEquals(2, value.getX());
357369
}
358370

359371
public void testBuilderMethodReturnInvalidType() throws Exception
360372
{
361373
final String json = "{\"x\":1}";
362374
try {
363-
mapper.readValue(json, ValueClassWrongBuildType.class);
375+
MAPPER.readValue(json, ValueClassWrongBuildType.class);
364376
fail("Missing expected JsonProcessingException exception");
365377
} catch(JsonProcessingException e) {
366378
assertTrue(
@@ -369,10 +381,18 @@ public void testBuilderMethodReturnInvalidType() throws Exception
369381
}
370382
}
371383

384+
public void testSelfBuilder777() throws Exception
385+
{
386+
SelfBuilder777 result = MAPPER.readValue(aposToQuotes("{'x':3}'"),
387+
SelfBuilder777.class);
388+
assertNotNull(result);
389+
assertEquals(3, result.x);
390+
}
391+
372392
public void testWithAnySetter822() throws Exception
373393
{
374394
final String json = "{\"extra\":3,\"foobar\":[ ],\"x\":1,\"name\":\"bob\"}";
375-
ValueClass822 value = mapper.readValue(json, ValueClass822.class);
395+
ValueClass822 value = MAPPER.readValue(json, ValueClass822.class);
376396
assertEquals(1, value.x);
377397
assertNotNull(value.stuff);
378398
assertEquals(3, value.stuff.size());
@@ -383,4 +403,6 @@ public void testWithAnySetter822() throws Exception
383403
assertTrue(ob instanceof List);
384404
assertTrue(((List<?>) ob).isEmpty());
385405
}
406+
407+
386408
}

0 commit comments

Comments
 (0)