Handle null values in serialization when the missing properties workaround is enabled#1235
Conversation
…round is enabled (elastic#557)
|
💚 CLA has been signed |
|
CLA signed. |
|
Hello @aOvOb, thanks a lot for contributing! This is a good solution for the issue, there's just a little problem that needs addressing:
You can test this yourself running: Instead of changing the jackson implementation code, IMO the best way to handle this is to have Another thing: the current unit tests didn't catch this behavior, so could you add those cases to the tests? Meaning Map and POJO serialization. Lastly, it would be ideal if to get a random json mapper implementation every time the unit tests are run. Thanks again :) |
|
Hello @l-trotta ! I've refactored the implementation as suggested:
Thanks again for the guidance :) |
|
@aOvOb thanks for the quick fixes, good work :) one last thing before merging: can you make the map and pojo unit test also use the random mapper? I know the bug was a jackson behavior specifically, but randomizing that test will help testing future additions too. |
Closes #557.
Problem
The documented workaround for
MissingRequiredPropertyException—ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true)— only fixes deserialization. Once active, required reference fields (String,BigDecimal,BigInteger,JsonValue) can benullin the deserialized object. Re-serializing such an object (most commonly via.toString()) then throwsNullPointerException, because generatedserializeInternalmethods call e.g.generator.write((String) null)and JSON-P providers like Parsson reject it.This is also the underlying cause of the workaround failure reported in #1082.
Approach
Introduce a package-private
NullSafeJsonGeneratorthat delegates to a wrappedJsonGeneratorbut translateswrite(...)calls with anullreference value into the correspondingwriteNull(...)call:write((String|BigDecimal|BigInteger|JsonValue) null)→writeNull()write(name, (String|BigDecimal|BigInteger|JsonValue) null)→writeNull(name)writeStartObject,writeKey, etc.) pass through unchanged.The wrapper is applied in
JsonpUtils.toString(JsonpSerializable, JsonpMapper, StringBuilder)andJsonpUtils.toJsonString(Object, JsonpMapper)only whenApiTypeHelper.requiredPropertiesCheckDisabled()returnstrue, so behavior in normal operation is unchanged.Test
Added
BehaviorsTest.testDangerousDisablePropertyCheckReferenceSerialization, modeled after the existingtestDangerousDisablePropertyCheckPrimitivebut omitting the requiredStringfieldcluster_namefrom aHealthResponse.Before this change the test fails with:
After the change the test passes and the response renders with
"cluster_name":null.All other serialization-related unit tests in
:java-client:testcontinue to pass.Scope / Notes
JsonpUtilsentry points used bytoString()paths. Users who callserializable.serialize(generator, mapper)directly with their ownJsonGeneratorare not covered —NullSafeJsonGeneratorcan be made public for that use case if maintainers prefer.