Search before asking

  • [x] I searched in the issues and found nothing similar.

Describe the bug

When calling mapper.valueToTree(UUID.randomUUID()), a NullPointerException is thrown inside the private _writeAsBinary(...) method. The root cause is that _writeCapabilities is null when ctxt.isEnabled(...) is checked.

Version Information

3.0.0-rc5

Reproduction

ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.valueToTree(UUID.randomUUID());

Expected behavior

No NullPointerException is thrown

Additional context

The root cause is that _assignGenerator isn’t called when valueToTree is invoked; since valueToTree isn’t actually performing serialization, it’s appropriate to handle it by not calling _assignGenerator.

here seem to be two possible approaches:

  1. Null-check in isEnabled Add a null check for _writeCapabilities inside isEnabled, and return false if it’s null. This is safe because valueToTree doesn’t actually serialize—instead, the JsonNode simply holds the UUID as a string.
public final boolean isEnabled(StreamWriteCapability cap) {
    return _wirteCapabilities != null && _writeCapabilities.isEnabled(cap);
}
  1. Default initialization in the SerializationContext Initialize _writeCapabilities with a default value when the SerializationContext is created. This ensures it’s never null, but may be wasteful since a fresh capabilities object will be created anyway once actual serialization occurs.
JacksonFeatureSet<StreamWriteCapability> _writeCapabilities
        = JacksonFeatureSet.fromDefaults(StreamWriteCapability.values());

Comment From: anthologia

@kiryong-lee

Thanks for reporting this!

I encountered this issue during our Jackson 3 migration in Spring Integration (spring-projects/spring-integration#10058) when valueToTree() is called with UUID objects in our JacksonJsonObjectMapper.toJsonNode() method:

https://github.com/spring-projects/spring-integration/blob/main/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapper.java

try {
    return this.objectMapper.valueToTree(json);  // NPE occurs here with UUID
}
catch (JacksonException e) {
    throw new IOException(e);
}

As a workaround, I registered a custom UUID serializer to the ObjectMapper to bypass the NPE.

Comment From: cowtowncoder

Thank you for reporting this @kiryong-lee.