Skip to content

feat(xml, yaml): add custom XmlBeanPropertyWriter and YAMLParser for enhanced serialization#51

Merged
essiembre merged 9 commits into
masterfrom
feature/jackson3
Jun 15, 2026
Merged

feat(xml, yaml): add custom XmlBeanPropertyWriter and YAMLParser for enhanced serialization#51
essiembre merged 9 commits into
masterfrom
feature/jackson3

Conversation

@essiembre

Copy link
Copy Markdown
Contributor
  • 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

…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>
Copilot AI review requested due to automatic review settings June 14, 2026 20:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.* to tools.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), and XmlTokenStream (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

  • currentProperty can be null (e.g., when serializing a root-level Map), but serialize() calls currentProperty.getAnnotation(...) (and later currentProperty.getName()), which will throw a NullPointerException. Since JsonXmlMapModule registers this serializer for Map.class globally, 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.

Comment thread src/main/java/tools/jackson/dataformat/yaml/YAMLParser.java
Comment on lines 43 to +46
if (consumerType != null
&& consumerType.getClass().isAssignableFrom(
beanDesc.getBeanClass())
|| Consumer.class.isAssignableFrom(beanDesc.getBeanClass())) {
beanClass)
|| Consumer.class.isAssignableFrom(beanClass)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed consumerType.getClass().isAssignableFrom(beanClass) to consumerType.isAssignableFrom(beanClass) and wrapped the && operands in explicit parentheses to clarify precedence over the ||.

Comment on lines 43 to +46
if (consumerType != null
&& consumerType.getClass().isAssignableFrom(
beanDesc.getBeanClass())
|| Consumer.class.isAssignableFrom(beanDesc.getBeanClass())) {
beanClass)
|| Consumer.class.isAssignableFrom(beanClass)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. Changed consumerType.getClass().isAssignableFrom(beanClass) to consumerType.isAssignableFrom(beanClass) and added explicit parentheses around the && subexpression to clarify precedence.

essiembre and others added 4 commits June 14, 2026 23:49
…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>
@essiembre essiembre merged commit 43a392d into master Jun 15, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants