feat(xml, yaml): add custom XmlBeanPropertyWriter and YAMLParser for enhanced serialization#51
Conversation
…enhanced serialization - Introduced XmlBeanPropertyWriter to handle XML serialization with support for null values, allowing default values to be resolved. - Implemented YAMLParser to utilize CoreScalarResolver for proper recognition of YAML null literals, improving POJO field mapping. - Both classes are modified copies from the Jackson library, tailored for specific serialization needs. Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
There was a problem hiding this comment.
Pull request overview
This PR upgrades the project’s Jackson integration to the relocated tools.jackson (Jackson 3.x) stack and introduces customized YAML/XML internals to preserve/restore specific serialization semantics (YAML null literals and XML empty element handling), while updating the BeanMapper and Flow modules accordingly.
Changes:
- Upgrade dependencies and codebase from
com.fasterxml.jackson.*totools.jackson.*(Jackson 3.0.4), including BeanMapper and Flow (de)serialization. - Add customized Jackson-internal copies:
YAMLParser(CoreSchema null literal handling),XmlBeanPropertyWriter(null/default inclusion behavior), andXmlTokenStream(EMPTY_ELEMENT_AS_NULL behavior). - Update XML collection/map/properties serializers/deserializers and associated tests to the new Jackson API.
Reviewed changes
Copilot reviewed 41 out of 41 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/test/java/com/norconex/commons/lang/flow/FlowSupportTest.java | Update test imports to tools.jackson annotations. |
| src/test/java/com/norconex/commons/lang/convert/ZoneIdConverterTest.java | Update test imports to tools.jackson mapper/annotations. |
| src/test/java/com/norconex/commons/lang/bean/stubs/TestConfig.java | Update XML annotation import to tools.jackson. |
| src/test/java/com/norconex/commons/lang/bean/jackson/JsonXmlCollectionTest.java | Update exception type imports to tools.jackson. |
| src/test/java/com/norconex/commons/lang/bean/DefaultValueTest.java | Remove obsolete Jackson checked exception from signature/imports. |
| src/test/java/com/norconex/commons/lang/bean/BeanMapperTest.java | Update expected exception type to tools.jackson DatabindException. |
| src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java | New customized YAML parser using CoreSchema scalar resolver. |
| src/main/java/tools/jackson/dataformat/xml/ser/XmlBeanPropertyWriter.java | New customized XML property writer to preserve null/default behaviors. |
| src/main/java/tools/jackson/dataformat/xml/deser/XmlTokenStream.java | New customized XML token stream restoring EMPTY_ELEMENT_AS_NULL semantics. |
| src/main/java/com/norconex/commons/lang/time/DurationParser.java | Use double parsing for numeric duration components. |
| src/main/java/com/norconex/commons/lang/map/PropertyMatchers.java | Switch Jackson annotation import to tools.jackson. |
| src/main/java/com/norconex/commons/lang/flow/module/StatementHandler.java | Update Flow handler signatures for new Jackson exception model. |
| src/main/java/com/norconex/commons/lang/flow/module/RootHandler.java | Migrate Flow parsing/writing to tools.jackson API and contexts. |
| src/main/java/com/norconex/commons/lang/flow/module/IfHandler.java | Migrate Flow IF handler to tools.jackson generator/token APIs. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowUtil.java | Replace failable functional interfaces; adapt to new parser/generator APIs. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowSerializerModifier.java | Port serializer modifier to tools.jackson modifier APIs. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowSerializer.java | Port Flow serializer to tools.jackson ValueSerializer model. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowModule.java | Switch module base class import to tools.jackson. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowDeserializerModifier.java | Port deserializer modifier to tools.jackson modifier APIs. |
| src/main/java/com/norconex/commons/lang/flow/module/FlowDeserializer.java | Port Flow deserializer to tools.jackson ValueDeserializer model. |
| src/main/java/com/norconex/commons/lang/flow/module/ConditionHandler.java | Use provided Jackson context for readValue instead of codec casting. |
| src/main/java/com/norconex/commons/lang/flow/module/ConditionGroupHandler.java | Port condition grouping handler token usage and exceptions. |
| src/main/java/com/norconex/commons/lang/flow/JsonFlow.java | Update annotation imports to tools.jackson. |
| src/main/java/com/norconex/commons/lang/convert/ZoneIdConverter.java | Port serializer signature to tools.jackson SerializationContext. |
| src/main/java/com/norconex/commons/lang/convert/GenericJsonSerializer.java | Port base serializer to tools.jackson ValueSerializer. |
| src/main/java/com/norconex/commons/lang/convert/GenericJsonModule.java | Switch module imports to tools.jackson. |
| src/main/java/com/norconex/commons/lang/convert/GenericJsonDeserializer.java | Port base deserializer to tools.jackson ValueDeserializer. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlPropertiesSerializer.java | Port XML properties serializer to tools.jackson generator APIs. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlPropertiesModule.java | Switch module import to tools.jackson. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlPropertiesDeserializer.java | Port deserializer to new tree-reading API and iteration style. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlMapSerializer.java | Port map serializer to tools.jackson generator/context APIs. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlMapModule.java | Switch module import to tools.jackson. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlMapDeserializer.java | Port map deserializer to tools.jackson token/context APIs. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlCollectionSerializer.java | Port collection serializer to tools.jackson and XML context types. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlCollectionModule.java | Port (de)serializer modifiers to tools.jackson modifier APIs. |
| src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlCollectionDeserializer.java | Port collection deserializer to tools.jackson APIs. |
| src/main/java/com/norconex/commons/lang/bean/jackson/EmptyWithClosingTagXmlFactory.java | Rework factory to force closing tags via pretty printer in Jackson 3 APIs. |
| src/main/java/com/norconex/commons/lang/bean/FailOnUnknownConfigurablePropModule.java | Port modifier/deserializer wiring to tools.jackson modifier/deserializer APIs. |
| src/main/java/com/norconex/commons/lang/bean/BeanMapper.java | Major BeanMapper refactor for Jackson 3 builder/configuration, YAML/XML features. |
| src/main/java/com/fasterxml/jackson/dataformat/xml/ser/XmlBeanPropertyWriter.java | Remove old custom class under com.fasterxml package. |
| pom.xml | Upgrade Jackson version and switch dependencies to relocated tools.jackson artifacts. |
Comments suppressed due to low confidence (1)
src/main/java/com/norconex/commons/lang/bean/jackson/JsonXmlMapSerializer.java:74
currentPropertycan be null (e.g., when serializing a root-levelMap), butserialize()callscurrentProperty.getAnnotation(...)(and latercurrentProperty.getName()), which will throw a NullPointerException. SinceJsonXmlMapModuleregisters this serializer forMap.classglobally, this can be hit in practice.
var entryName = DEFAULT_ENTRY_NAME;
var keyName = "key";
var valueName = "value";
var annot = currentProperty.getAnnotation(JsonXmlMap.class);
if (annot != null) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (consumerType != null | ||
| && consumerType.getClass().isAssignableFrom( | ||
| beanDesc.getBeanClass()) | ||
| || Consumer.class.isAssignableFrom(beanDesc.getBeanClass())) { | ||
| beanClass) | ||
| || Consumer.class.isAssignableFrom(beanClass)) { |
There was a problem hiding this comment.
Fixed in the latest commit. Changed consumerType.getClass().isAssignableFrom(beanClass) to consumerType.isAssignableFrom(beanClass) and added explicit parentheses around the && condition to make the &&/|| precedence clear.
There was a problem hiding this comment.
Fixed — changed consumerType.getClass().isAssignableFrom(beanClass) to consumerType.isAssignableFrom(beanClass) and wrapped the && operands in explicit parentheses to clarify precedence over the ||.
| if (consumerType != null | ||
| && consumerType.getClass().isAssignableFrom( | ||
| beanDesc.getBeanClass()) | ||
| || Consumer.class.isAssignableFrom(beanDesc.getBeanClass())) { | ||
| beanClass) | ||
| || Consumer.class.isAssignableFrom(beanClass)) { |
There was a problem hiding this comment.
Fixed in the latest commit. Changed consumerType.getClass().isAssignableFrom(beanClass) to consumerType.isAssignableFrom(beanClass) and added explicit parentheses around the && subexpression to clarify precedence.
…flow configurations Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
…support for attributes and various numeric formats Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
…alizerModifier to prevent wrapping non-Consumer types Signed-off-by: Pascal Essiembre <pascal.essiembre@norconex.com>
Signed-off-by: Pascal Essiembre pascal.essiembre@norconex.com