Skip to content

Commit

Permalink
Fixed #442 (missing START_OBJECT for leading "mixed text")
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Mar 30, 2021
1 parent 43a0881 commit 6c37f48
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 25 deletions.
3 changes: 2 additions & 1 deletion release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Project: jackson-dataformat-xml

2.13.0 (not yet released)

No changes since 2.12
#442: Missing `START_OBJECT` token in complex element starting with text
(reported by richardsonwk@github)

2.12.3 (not yet released)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private Feature(boolean defaultState) {
*/
protected boolean _closed;

final protected IOContext _ioContext;
protected final IOContext _ioContext;

/*
/**********************************************************
Expand All @@ -179,6 +179,16 @@ private Feature(boolean defaultState) {

protected String _currText;

/**
* Additional flag that is strictly needed when exposing "mixed" leading
* String value as "anonymous" property/string pair. If so, code returns
* START_OBJECT first, sets {@code _nextToken} to be {@code FIELD_NAME}
* and sets this flag to indicate use of "anonymous" marker.
*
* @since 2.13
*/
protected boolean _nextIsLeadingMixed;

/*
/**********************************************************
/* Parsing state, parsed values
Expand Down Expand Up @@ -668,7 +678,15 @@ public JsonToken nextToken() throws IOException
_parsingContext = _parsingContext.getParent();
break;
case FIELD_NAME:
_parsingContext.setCurrentName(_xmlTokens.getLocalName());
// 29-Mar-2021, tatu: [dataformat-xml#442]: special case of leading
// mixed text added
if (_nextIsLeadingMixed) {
_nextIsLeadingMixed = false;
_parsingContext.setCurrentName(_cfgNameForTextElement);
_nextToken = JsonToken.VALUE_STRING;
} else {
_parsingContext.setCurrentName(_xmlTokens.getLocalName());
}
break;
default: // VALUE_STRING, VALUE_NULL
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index` anyway; not
Expand Down Expand Up @@ -756,7 +774,7 @@ public JsonToken nextToken() throws IOException
_currText = _xmlTokens.getText();
if (_mayBeLeaf) {
_mayBeLeaf = false;
// One more refinement (pronunced like "hack") is that if
// One more refinement (pronounced like "hack") is that if
// we had an empty String (or all white space), and we are
// deserializing an array, we better hide the empty text.
// Also: must skip following END_ELEMENT
Expand Down Expand Up @@ -792,7 +810,14 @@ public JsonToken nextToken() throws IOException
// but... [dataformat-xml#191]: looks like we can't short-cut, must
// loop over again
if (_parsingContext.inObject()) {
if ((_currToken != JsonToken.FIELD_NAME) && XmlTokenStream._allWs(_currText)) {
if (_currToken == JsonToken.FIELD_NAME) {
// 29-Mar-2021, tatu: [dataformat-xml#442]: need special handling for
// leading mixed content; requires 3-token sequence for which _nextToken
// along is not enough.
_nextIsLeadingMixed = true;
_nextToken = JsonToken.FIELD_NAME;
return (_currToken = JsonToken.START_OBJECT);
} else if (XmlTokenStream._allWs(_currText)) {
token = _nextToken();
continue;
}
Expand All @@ -802,6 +827,11 @@ public JsonToken nextToken() throws IOException
token = _nextToken();
continue;
}
// 29-Mar-2021, tatu: This seems like an error condition...
// How should we indicate it? As of 2.13, report as unexpected state
throw _constructError(
"Unexpected non-whitespace text ('"+_currText+"' in Array context: should not occur (or should be handled)"
);
}

// If not a leaf (or otherwise ignorable), need to transform into property...
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.fasterxml.jackson.dataformat.xml.failing;
package com.fasterxml.jackson.dataformat.xml.stream;

import com.fasterxml.jackson.core.JsonToken;

Expand All @@ -11,26 +11,26 @@ public class XmlParser442Test extends XmlTestBase
private final XmlMapper MAPPER = newMapper();

// For [dataformat-xml#442]
public void testMixedContentAfter() throws Exception
public void testMixedContentBeforeElement442() throws Exception
{
try (FromXmlParser xp = (FromXmlParser) MAPPER.createParser(
"<root>\n" // START_OBJECT
+" <branch>\n" // *Missing* START_OBJECT
+" text\n"
+" <leaf>stuff</leaf>\n"
+" </branch>\n" // END_OBJECT
+"</root>\n" // END_OBJECT

/*
"<SomeXml>\n" // START_OBJECT
+" <ParentElement>\n" // *Missing* START_OBJECT
+" text\n"
+" <ChildElement someAttribute=\"value\"/>\n" // START_OBJECT/END_OBJECT
+" further text\n"
+" </ParentElement>\n" // END_OBJECT
+"</SomeXml>\n" // END_OBJECT
*/
)) {
final String XML =
"<root>\n" // START_OBJECT
+" <branch>\n" // *Missing* START_OBJECT
+" text\n"
+" <leaf>stuff</leaf>\n"
+" </branch>\n" // END_OBJECT
+"</root>\n" // END_OBJECT
;

// Should get equivalent of:
//
// { "branch" : {
// "" : " text ",
// "leaf" : "stuff"
// }
// }

try (FromXmlParser xp = (FromXmlParser) MAPPER.createParser(XML)) {
assertToken(JsonToken.START_OBJECT, xp.nextToken());
assertToken(JsonToken.FIELD_NAME, xp.nextToken());
assertEquals("branch", xp.currentName());
Expand Down

0 comments on commit 6c37f48

Please sign in to comment.