Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ assertEquals(JsonNullable.<String>undefined(), mapper.readValue("{}", Pet.class)

```

`JsonNullable` can also be used as a `@JsonCreator` constructor parameter.
An absent property is passed to the constructor as `JsonNullable.undefined()` rather than as `null`, so it stays distinguishable from an explicit `null`.

The `ValueExtractor` is registered automatically via Java Service loader mechanism. The example class above will validate as follows
```java
// instantiate javax.validation.Validator
Expand All @@ -89,6 +92,4 @@ assertEquals(1, validationResult.size());

## Limitations

* Doesn't work when passed as a parameter to a `@JsonCreator` constructor (non present field gets deserialized as null instead of undefined).
But as JsonNullable is here to represent "optional" values, there shouldn't be a need to put it in a constructor.
* Doesn't work with `@JsonUnwrapped`.
23 changes: 18 additions & 5 deletions src/test/java/org/openapitools/jackson/nullable/CreatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

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

// TODO: fix JsonNullable in constructor annotated by JsonCreator
@Disabled("JsonNullable in a constructor is deserialized to JsonNullable[null] instead of JsonNullable.undefined")
class CreatorTest extends ModuleTestBase {
static class CreatorWithJsonNullableStrings {
JsonNullable<String> a, b;

// note: something weird with test setup, should not need annotations
// note: parameter names are not retained by default, hence the explicit @JsonProperty
@JsonCreator
public CreatorWithJsonNullableStrings(@JsonProperty("a") JsonNullable<String> a,
@JsonProperty("b") JsonNullable<String> b) {
Expand Down Expand Up @@ -45,5 +42,21 @@ void testCreatorWithJsonNullable(JsonProcessor jsonProcessor) throws Exception {
assertTrue(bean.a.isPresent());
assertFalse(bean.b.isPresent());
assertEquals("foo", bean.a.get());
assertEquals(JsonNullable.<String>undefined(), bean.b);
}
}

/**
* An absent creator property has to stay distinguishable from one that is
* explicitly set to <code>null</code>, which is the reason JsonNullable exists.
*/
@ParameterizedTest
@MethodSource("jsonProcessors")
void testCreatorSeparatesExplicitNullFromAbsent(JsonProcessor jsonProcessor) throws Exception {
jsonProcessor.mapperWithModule();
CreatorWithJsonNullableStrings bean = jsonProcessor.readValue(
aposToQuotes("{'a':null}"), CreatorWithJsonNullableStrings.class);
assertNotNull(bean);
assertEquals(JsonNullable.<String>of(null), bean.a);
assertEquals(JsonNullable.<String>undefined(), bean.b);
}
}