Skip to content

Commit 70dd97e

Browse files
committed
Fix #397 (alas, no unit tests)
1 parent 69a9028 commit 70dd97e

File tree

4 files changed

+41
-38
lines changed

4 files changed

+41
-38
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Project: jackson-dataformat-xml
1010
(reported by Joseph P)
1111
#318: XMLMapper fails to deserialize null (POJO reference) from blank tag
1212
(reported by Jochen S)
13+
#397: `XmlReadContext` does not keep track of array index
1314

1415
2.11.1 (not yet released)
1516

src/main/java/com/fasterxml/jackson/dataformat/xml/deser/FromXmlParser.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -472,15 +472,16 @@ public JsonToken nextToken() throws IOException
472472
{
473473
JsonToken t = nextToken0();
474474
if (t != null) {
475+
final String loc = _parsingContext.pathAsPointer().toString();
475476
switch (t) {
476477
case FIELD_NAME:
477-
System.out.println("FromXmlParser.nextToken(): JsonToken.FIELD_NAME '"+_parsingContext.getCurrentName()+"'");
478+
System.out.printf("FromXmlParser.nextToken() at '%s': JsonToken.FIELD_NAME '%s'\n", loc, _parsingContext.getCurrentName());
478479
break;
479480
case VALUE_STRING:
480-
System.out.println("FromXmlParser.nextToken(): JsonToken.VALUE_STRING '"+getText()+"'");
481+
System.out.printf("FromXmlParser.nextToken() at '%s': JsonToken.VALUE_STRING '%s'\n", loc, getText());
481482
break;
482483
default:
483-
System.out.println("FromXmlParser.nextToken(): "+t);
484+
System.out.printf("FromXmlParser.nextToken() at '%s': %s\n", loc, t);
484485
}
485486
}
486487
return t;
@@ -496,6 +497,7 @@ public JsonToken nextToken() throws IOException
496497
JsonToken t = _nextToken;
497498
_currToken = t;
498499
_nextToken = null;
500+
499501
switch (t) {
500502
case START_OBJECT:
501503
_parsingContext = _parsingContext.createChildObjectContext(-1, -1);
@@ -511,7 +513,9 @@ public JsonToken nextToken() throws IOException
511513
_parsingContext.setCurrentName(_xmlTokens.getLocalName());
512514
break;
513515
default: // VALUE_STRING, VALUE_NULL
514-
// should be fine as is?
516+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index` anyway; not
517+
// used for Object contexts, updated automatically by "createChildXxxContext"
518+
_parsingContext.valueStarted();
515519
}
516520
return t;
517521
}
@@ -574,6 +578,8 @@ public JsonToken nextToken() throws IOException
574578
}
575579
// 07-Sep-2019, tatu: for [dataformat-xml#353], must NOT return second null
576580
if (_currToken != JsonToken.VALUE_NULL) {
581+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
582+
_parsingContext.valueStarted();
577583
return (_currToken = JsonToken.VALUE_NULL);
578584
}
579585
}
@@ -594,6 +600,8 @@ public JsonToken nextToken() throws IOException
594600
return (_currToken = JsonToken.FIELD_NAME);
595601
case XmlTokenStream.XML_ATTRIBUTE_VALUE:
596602
_currText = _xmlTokens.getText();
603+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
604+
_parsingContext.valueStarted();
597605
return (_currToken = JsonToken.VALUE_STRING);
598606
case XmlTokenStream.XML_TEXT:
599607
_currText = _xmlTokens.getText();
@@ -676,6 +684,8 @@ public String nextTextValue() throws IOException
676684

677685
// expected case; yes, got a String
678686
if (t == JsonToken.VALUE_STRING) {
687+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
688+
_parsingContext.valueStarted();
679689
return _currText;
680690
}
681691
_updateState(t);
@@ -725,6 +735,8 @@ public String nextTextValue() throws IOException
725735
// NOTE: this is different from nextToken() -- produce "", NOT null
726736
_mayBeLeaf = false;
727737
_currToken = JsonToken.VALUE_STRING;
738+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
739+
_parsingContext.valueStarted();
728740
return (_currText = "");
729741
}
730742
_currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT;
@@ -745,6 +757,8 @@ public String nextTextValue() throws IOException
745757
break;
746758
case XmlTokenStream.XML_ATTRIBUTE_VALUE:
747759
_currToken = JsonToken.VALUE_STRING;
760+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
761+
_parsingContext.valueStarted();
748762
return (_currText = _xmlTokens.getText());
749763
case XmlTokenStream.XML_TEXT:
750764
_currText = _xmlTokens.getText();
@@ -758,6 +772,8 @@ public String nextTextValue() throws IOException
758772
}
759773
// NOTE: this is different from nextToken() -- NO work-around
760774
// for otherwise empty List/array
775+
// 13-May-2020, tatu: [dataformat-xml#397]: advance `index`
776+
_parsingContext.valueStarted();
761777
_currToken = JsonToken.VALUE_STRING;
762778
return _currText;
763779
}

src/main/java/com/fasterxml/jackson/dataformat/xml/deser/XmlReadContext.java

+20-18
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public static XmlReadContext createRootContext() {
105105

106106
public final XmlReadContext createChildArrayContext(int lineNr, int colNr)
107107
{
108+
++_index; // not needed for Object, but does not hurt so no need to check curr type
108109
XmlReadContext ctxt = _child;
109110
if (ctxt == null) {
110111
_child = ctxt = new XmlReadContext(this, TYPE_ARRAY, lineNr, colNr);
@@ -116,6 +117,7 @@ public final XmlReadContext createChildArrayContext(int lineNr, int colNr)
116117

117118
public final XmlReadContext createChildObjectContext(int lineNr, int colNr)
118119
{
120+
++_index; // not needed for Object, but does not hurt so no need to check curr type
119121
XmlReadContext ctxt = _child;
120122
if (ctxt == null) {
121123
_child = ctxt = new XmlReadContext(this, TYPE_OBJECT, lineNr, colNr);
@@ -127,7 +129,7 @@ public final XmlReadContext createChildObjectContext(int lineNr, int colNr)
127129

128130
/*
129131
/**********************************************************
130-
/* Abstract method implementation
132+
/* Abstract method implementation, overrides
131133
/**********************************************************
132134
*/
133135

@@ -140,18 +142,16 @@ public final XmlReadContext createChildObjectContext(int lineNr, int colNr)
140142
@Override
141143
public final XmlReadContext getParent() { return _parent; }
142144

143-
/*
144-
/**********************************************************
145-
/* State changes
146-
/**********************************************************
145+
/**
146+
* @return Location pointing to the point where the context
147+
* start marker was found
147148
*/
149+
@Override
150+
public final JsonLocation getStartLocation(Object srcRef) {
151+
// We don't keep track of offsets at this level (only reader does)
152+
long totalChars = -1L;
148153

149-
public final boolean expectComma() {
150-
throw new UnsupportedOperationException();
151-
}
152-
153-
public void setCurrentName(String name) {
154-
_currentName = name;
154+
return new JsonLocation(srcRef, totalChars, _lineNr, _columnNr);
155155
}
156156

157157
/*
@@ -161,15 +161,17 @@ public void setCurrentName(String name) {
161161
*/
162162

163163
/**
164-
* @return Location pointing to the point where the context
165-
* start marker was found
164+
* Method called to mark start of new value, mostly to update `index`
165+
* for Array and Root contexts.
166+
*
167+
* @since 2.12
166168
*/
167-
@Override
168-
public final JsonLocation getStartLocation(Object srcRef) {
169-
// We don't keep track of offsets at this level (only reader does)
170-
long totalChars = -1L;
169+
public final void valueStarted() {
170+
++_index;
171+
}
171172

172-
return new JsonLocation(srcRef, totalChars, _lineNr, _columnNr);
173+
public void setCurrentName(String name) {
174+
_currentName = name;
173175
}
174176

175177
public void setNamesToWrap(Set<String> namesToWrap) {

src/test/java/com/fasterxml/jackson/dataformat/xml/lists/ListDeser393Test.java

-16
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import java.util.*;
44

5-
import com.fasterxml.jackson.annotation.JsonInclude;
6-
75
import com.fasterxml.jackson.databind.ObjectMapper;
86

97
import com.fasterxml.jackson.dataformat.xml.XmlTestBase;
@@ -12,20 +10,6 @@
1210

1311
public class ListDeser393Test extends XmlTestBase
1412
{
15-
@JacksonXmlRootElement(localName = "result")
16-
@JsonInclude(JsonInclude.Include.NON_NULL)
17-
static class Value393 {
18-
private Prices393 prices = new Prices393();
19-
20-
public void setPrices(Prices393 prices) {
21-
this.prices = prices;
22-
}
23-
24-
public Prices393 getPrices() {
25-
return this.prices;
26-
}
27-
}
28-
2913
@JacksonXmlRootElement(localName = "prices")
3014
static class Prices393 {
3115
private List<Price393> price = new ArrayList<Price393>();

0 commit comments

Comments
 (0)