Repository navigation
Apply XmlNameProcessor consistently to all written element/attribute names - #918
Merged
Merged
Conversation
Sahana2524
force-pushed
the
wrapper-name-encode
branch
from
September 27, 2026 15:27
2f112c2 to
98f21c1
Compare
1 similar comment
XmlNameProcessor
Contributor
Author
|
any update? |
Root names from class name, @JsonRootName or withRootName() were written without going through the XmlNameProcessor, so AlwaysOn base64 round trips failed for most POJOs. Encode in _initWithRootName() (covering all root paths, including unwrapped ObjectNode) and move RootNameEncodingTest out of tofix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asterXML#918) Names passed via setNextName()/setNextNameIfMissing(), writeName() and the startWrappedValue() wrapper now all go through one helper, _encodeName(), so _nextName always holds the encoded name. Fixes item names set via startWrappedValue() (used with writeRepeatedPropertyName()) being written unencoded, and avoids double encoding by replacing the (unreleased) public encodeContentName() with protected _encodeName(). Reuses existing QName when processor leaves name unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h configured mapper - Add indented variant of AlwaysOn base64 wrapped collection round trip, covering wrapper start element written via XmlPrettyPrinter - Read Replacement processor output back with the configured mapper into a DTO declaring replaced names, verifying wrapper is recognized on read - Import JacksonXmlElementWrapper; reference FasterXML#918 in test comments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…asterXML#918) Keep the unencoded name next to _nextName (_nextNameRaw), so that: - writeName() does not re-encode the name a bean serializer already set via setNextName() (each name now encoded once per write, not twice) - namespace carried over by writeName() is the unencoded one - writeRepeatedPropertyName() registers unencoded name in stream context, same as writeName() Also: - Encode root attribute names (except XSI ones meant for other tools) - Set default namespace from encoded root name in _initWithRootName() - Preserve prefix when re-creating encoded QName; simplify _encodeName() - Correct _nextName javadoc (fixed names are not encoded) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… names (FasterXML#918) - Only trust _nextNameRaw while _nextName is still the QName encoded from it (_nextNameEncoded), so direct assignments to _nextName (subclasses, internal restores) cannot leave a stale raw name; drops manual resets - XSI namespace names are standard names: ToXmlGenerator._encodeName() leaves them as-is and XmlTokenStream._decodeName() no longer decodes them, so literal xsi:* attributes (e.g. xsi:noNamespaceSchemaLocation) no longer fail to decode with base64 name processors Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
XmlNameProcessorXmlNameProcessor consistently to all written element/attribute names
…asterXML#918) - Allow setNextName(null) / setNextNameIfMissing(null) again (clears name) - Bean serializers set unencoded property name via _setNextPropertyName(); the following writeName() encodes it, so names of properties not written (nulls, filtered out) are no longer encoded - _initWithRootName(): take default namespace from the name actually set, instead of encoding root name a second time - Never encode/decode names in the standard xml: namespace (xml:lang etc), same as XSI names - Rename _nextNameRaw() accessor to _validNextNameRaw() Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…encodes (FasterXML#918) - Never encode names in the xmlns namespace (namespace declarations given as root attributes), same as XSI and xml: names - writeName() no longer carries over XSI/xml/xmlns namespace of previous name to content names (which also skipped their encoding) - Bean property name pending encoding is encoded by writeName() without allocating another QName - startWrappedValue(): reuse encoded wrapper name for items when same - Javadoc: _nextName is unencoded between _setNextPropertyName() and writeName() Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…terXML#918) - Rename package-private _setNextPropertyName() to setNextPropertyName() - startWrappedValue(): accept null wrappedName again (clears name) - _validNextNameRaw(): never consider raw name valid for null _nextName - Factor out _setNextName(raw, encoded); fix _nextIsXsiType javadoc Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cowtowncoder
approved these changes
Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Collection wrapper element name skips the
XmlNameProcessorstartWrappedValue()writes the wrapper element straight to the Stax writer, so with a non-passthrough processor the wrapper name comes out verbatim while the wrapped item names (which go throughwriteName()) are encoded. Since the reader decodes every element name, a default wrappedListserialized withnewAlwaysOnBase64Processor()then throwsStreamReadExceptionon read (the raw wrapper name is not valid base64), and a wrapper name holding an XML-invalid character such as a space emits non-well-formed XML. Passthrough output is unchanged.Scope grew during review: names encoded at a single point
The same class of bug existed for other names that reached the Stax writer without going through the processor, so the fix was generalized:
ToXmlGenerator._encodeName()is now the one place names are encoded.setNextName()/setNextNameIfMissing()encode their argument, as dowriteName()and the wrapper name instartWrappedValue()._nextNamealways holds the name as written.@JsonRootName,ObjectWriter.withRootName()) are now encoded; previously e.g. a classPointbroke the AlwaysOn base64 round trip.tofix/RootNameEncodingTestmoved tomisc/. The default namespace set in_initWithRootName()follows the encoded name.XmlGeneratorInitializer.addRootAttribute()are now encoded, so they can be read back like other attributes.xsi,xmlandxmlnsnamespaces are a fixed vocabulary:_encodeName()leaves them as-is, andXmlTokenStream._decodeName()no longer decodesxsi/xmlnames (StAX never reportsxmlnsdeclarations as attributes). Literal attributes such asxsi:noNamespaceSchemaLocationorxml:lang, and namespace declarations added as root attributes, stay usable by other XML tools and no longer fail with a name-decode error under base64 processors.writeName()also no longer carries these namespaces over from a preceding property to content names (Map /@JsonAnyGetterkeys), which would have skipped their encoding._nextName, sosetNextName()followed bywriteName()of the same name does not encode twice, and namespaces are not processed twice; collection items reuse the encoded wrapper name when both are the same. This shortcut only applies while_nextNameis still the exact name encoded from it, so direct assignments (subclasses, internal restores) cannot leave it stale. Bean serializers pass the unencoded property name and let the followingwriteName()encode it, so properties that end up not written (nulls, filtered out) are never encoded. The stream write context tracks unencoded names.API / behavior changes (3.3.0, unreleased)
ToXmlGenerator.encodeContentName()(public, added in ApplyXmlNameProcessorto unwrappedObjectNoderoot element name #887, never released) is replaced by protected_encodeName(). Callers now always pass unencoded names, which removes the risk of double encoding.XmlNameProcessor, names passed tosetNextName()/setNextNameIfMissing()by custom serializers, and root attribute names, are now encoded. Before, they were written verbatim and could not be read back.xsi,xmlandxmlnsnamespaces (including bean properties explicitly declared in them) are no longer encoded on write or decoded on read. Content names following such a property no longer inherit its namespace. Compatibility note: with the AlwaysOn base64 processor, 3.2 wrote bean properties explicitly declared in thexsiorxmlnamespace with encoded names (e.g.xml:bGFuZw); 3.3 reads such names literally, so those properties will not match when reading XML written by 3.2. (The plain Base64 processor leaves valid names unchanged, so it is not affected for them.)Tests (in
XmlNameEscapeTestandRootNameEncodingTest)setNextName(),startWrappedValue(),writeRepeatedPropertyName()).xsi:,xml:langandxmlns:attributes left literal; reading works with and withoutSKIP_UNKNOWN_XSI_ATTRIBUTES.xsi-namespaced property is encoded (Replacement processor).setNextName(null)still clears the pending name.🤖 Generated with Claude Code