Skip to content

Commit

Permalink
Implement #3676
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Nov 21, 2022
1 parent 7f243a5 commit 2c77b62
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 2 deletions.
5 changes: 5 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Project: jackson-databind
=== Releases ===
------------------------------------------------------------------------

2.15.0 (not yet released)

#3676: Allow use of `@JsonCreator(mode = Mode.PROPERTIES)` creator for POJOs
with"empty String" coercion

2.14.1 (not yet released)

#3655: `Enum` values can not be read from single-element array even with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,11 @@ public AccessPattern getEmptyAccessPattern() {
public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
// alas, need to promote exception, if any:
try {
return _valueInstantiator.createUsingDefault(ctxt);
// 20-Nov-2022, tatu: Ok one more complication; may want to consider
// EITHER default Creator OR properties-one with no args.
// But that is encapsulated by `ValueInstantiator` now
// return _valueInstantiator.createUsingDefault(ctxt);
return _valueInstantiator.createUsingDefaultOrWithoutArguments(ctxt);
} catch (IOException e) {
return ClassUtil.throwAsMappingException(ctxt, e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) t
"no creator with arguments specified");
}

/**
* Combination of {@link #createUsingDefault} and {@link #createFromObjectWith(DeserializationContext, Object[])}
* which will call former first, if possible; or latter if possible (with {@code null}
* arguments); and if neither works throw an exception.
*
* @since 2.15
*/
//public abstract Object createUsingDefaultOrWithoutArguments(DeserializationContext ctxt) throws IOException;
public Object createUsingDefaultOrWithoutArguments(DeserializationContext ctxt) throws IOException {
return ctxt.handleMissingInstantiator(getValueClass(), this, null,
"neither default (no-arguments) nor with-arguments Creator found");
}

/**
* Method that delegates to
* {@link #createFromObjectWith(DeserializationContext, Object[])} by
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,17 @@ public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) t
}
}

@Override
public Object createUsingDefaultOrWithoutArguments(DeserializationContext ctxt) throws IOException {
if (_defaultCreator != null) { // sanity-check; caller should check
return createUsingDefault(ctxt);
}
if (_withArgsCreator != null) {
return createFromObjectWith(ctxt, new Object[_constructorArguments.length]);
}
return super.createUsingDefaultOrWithoutArguments(ctxt);
}

@Override
public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.fasterxml.jackson.databind.convert;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JacksonException;

import com.fasterxml.jackson.databind.*;
Expand All @@ -14,11 +16,20 @@ static class Bean {
public String a;
}

private final ObjectMapper MAPPER = newJsonMapper();
static class BeanWithProp3676 {
@JsonCreator
public BeanWithProp3676(@JsonProperty("a") String a) {
this.a = a;
}

public String a;
}

private final String JSON_EMPTY = q("");
private final String JSON_BLANK = q(" ");

private final ObjectMapper MAPPER = newJsonMapper();

/*
/********************************************************
/* Test methods, from empty String
Expand Down Expand Up @@ -52,6 +63,22 @@ public void testPOJOFromEmptyPhysicalTypeConfig() throws Exception
_testPOJOFromEmptyPhysicalTypeConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null);
}

// [databind#3676] Alternative test for "Mode.PROPERTIES" variant where we
// have no "default" constructor
public void testPOJOFromEmptyWithProperties() throws Exception
{
// Then coerce as empty
ObjectMapper mapper = jsonMapperBuilder()
.withCoercionConfigDefaults(h -> {
h.setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
})
.build();
BeanWithProp3676 b = mapper.readerFor(BeanWithProp3676.class)
.readValue(JSON_EMPTY);
assertNotNull(b);
assertNull(b.a);
}

/*
/********************************************************
/* Test methods, from blank String
Expand Down

0 comments on commit 2c77b62

Please sign in to comment.