9

I'm trying to use JsonNullable<String> to distinguish between the absence of a value and null. When I serialize my Java object, User, the JsonNullable<String> field is serialized as a JSON object with value

{"present":false}

I'm expecting it to print {} since I initialized the field with undefined.

Here's my class

public class User { 
  @JsonProperty("userId")
  private JsonNullable<String> userId = JsonNullable.undefined();

  //set and get
  //tostring
}

and a small driver program where I actually set a value within the JsonNullable field.

User user = new User();
user.setUserId(JsonNullable.of("12345"));

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());

String expectedData = objectMapper.writeValueAsString(user);
System.out.println(expectedData);

This prints

{"userId":{"present":true}}

But I expected

{"userId":"12345"}

In other words, I expected the value wrapped within the JsonNullable to be serialized into the JSON. Why are JsonNullable and Jackson behaving this way?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Surya Prakash
  • 105
  • 1
  • 1
  • 4

3 Answers3

8

As the wiki instructs, you need to register the corresponding module (in addition to any others you have):

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.registerModule(new JsonNullableModule());
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
8

Add the following configuration in Spring Boot:

@Configuration
public class JacksonConfiguration {
    @Bean
    public JsonNullableModule jsonNullableModule() {
        return new JsonNullableModule();
    }
}
akasha
  • 494
  • 6
  • 4
  • This works perfectly fine. Also this is the required dependency: ` org.openapitools jackson-databind-nullable 0.2.0 ` – marcel Feb 01 '23 at 11:04
1

Registering the JsonNullableModule is the correct solution. But I just want to point out that JsonNullable doesn't play well with openapi-generator. We generate client APIs from the backend controller annotations. The required, nullable annotations on @schema didn't work for us (on a Kotlin data class). We went back with using Optional<T>? and worked out perfectly with out any extra annotations needed.

X.Y.
  • 13,726
  • 10
  • 50
  • 63