36
36
37
37
/**
38
38
* A JSONP parser implementation on top of Jackson.
39
+ * <p>
40
+ * <b>Warning:</b> this implementation isn't fully compliant with the JSONP specification: calling {@link #hasNext()}
41
+ * moves forward the underlying Jackson parser as Jackson doesn't provide an equivalent method. This means no value
42
+ * getter method (e.g. {@link #getInt()} or {@link #getString()} should be called until the next call to {@link #next()}.
43
+ * Such calls will throw an {@code IllegalStateException}.
39
44
*/
40
45
public class JacksonJsonpParser implements JsonParser {
41
46
42
47
private final com .fasterxml .jackson .core .JsonParser parser ;
43
48
44
- private JsonToken nextToken ;
45
- private boolean hadFirstToken = false ;
49
+ private boolean hasNextWasCalled = false ;
46
50
47
51
private static final EnumMap <JsonToken , Event > tokenToEvent ;
48
52
@@ -80,46 +84,55 @@ private JsonParsingException convertException(IOException ioe) {
80
84
return new JsonParsingException ("Jackson exception" , ioe , getLocation ());
81
85
}
82
86
83
- private void fetchNextToken () {
87
+ private JsonToken fetchNextToken () {
84
88
try {
85
- nextToken = parser .nextToken ();
89
+ return parser .nextToken ();
86
90
} catch (IOException e ) {
87
91
throw convertException (e );
88
92
}
89
93
}
90
94
95
+ private void ensureTokenIsCurrent () {
96
+ if (hasNextWasCalled ) {
97
+ throw new IllegalStateException ("Cannot get event data as parser as already been moved to the next event" );
98
+ }
99
+ }
100
+
91
101
@ Override
92
102
public boolean hasNext () {
93
- if (!hadFirstToken ) {
94
- hadFirstToken = true ;
95
- fetchNextToken ();
103
+ if (hasNextWasCalled ) {
104
+ return parser .currentToken () != null ;
105
+ } else {
106
+ hasNextWasCalled = true ;
107
+ return fetchNextToken () != null ;
96
108
}
97
-
98
- return nextToken != null ;
99
109
}
100
110
101
111
@ Override
102
112
public Event next () {
103
- if (!hadFirstToken ) {
104
- hadFirstToken = true ;
105
- fetchNextToken ();
113
+ JsonToken token ;
114
+ if (hasNextWasCalled ) {
115
+ token = parser .getCurrentToken ();
116
+ hasNextWasCalled = false ;
117
+ } else {
118
+ token = fetchNextToken ();
106
119
}
107
120
108
- if (nextToken == null ) {
121
+ if (token == null ) {
109
122
throw new NoSuchElementException ();
110
123
}
111
124
112
- Event result = tokenToEvent .get (nextToken );
125
+ Event result = tokenToEvent .get (token );
113
126
if (result == null ) {
114
- throw new JsonParsingException ("Unsupported Jackson event type " + nextToken .toString (), getLocation ());
127
+ throw new JsonParsingException ("Unsupported Jackson event type " + token .toString (), getLocation ());
115
128
}
116
129
117
- fetchNextToken ();
118
130
return result ;
119
131
}
120
132
121
133
@ Override
122
134
public String getString () {
135
+ ensureTokenIsCurrent ();
123
136
try {
124
137
return parser .getValueAsString ();
125
138
} catch (IOException e ) {
@@ -129,11 +142,13 @@ public String getString() {
129
142
130
143
@ Override
131
144
public boolean isIntegralNumber () {
145
+ ensureTokenIsCurrent ();
132
146
return parser .isExpectedNumberIntToken ();
133
147
}
134
148
135
149
@ Override
136
150
public int getInt () {
151
+ ensureTokenIsCurrent ();
137
152
try {
138
153
return parser .getIntValue ();
139
154
} catch (IOException e ) {
@@ -143,6 +158,7 @@ public int getInt() {
143
158
144
159
@ Override
145
160
public long getLong () {
161
+ ensureTokenIsCurrent ();
146
162
try {
147
163
return parser .getLongValue ();
148
164
} catch (IOException e ) {
@@ -152,6 +168,7 @@ public long getLong() {
152
168
153
169
@ Override
154
170
public BigDecimal getBigDecimal () {
171
+ ensureTokenIsCurrent ();
155
172
try {
156
173
return parser .getDecimalValue ();
157
174
} catch (IOException e ) {
@@ -177,6 +194,11 @@ public void close() {
177
194
178
195
@ Override
179
196
public JsonObject getObject () {
197
+ ensureTokenIsCurrent ();
198
+ if (parser .currentToken () != JsonToken .START_OBJECT ) {
199
+ throw new IllegalStateException ("Unexpected token " + parser .currentToken () +
200
+ " at " + parser .getTokenLocation ());
201
+ }
180
202
if (valueParser == null ) {
181
203
valueParser = new JsonValueParser ();
182
204
}
@@ -189,9 +211,14 @@ public JsonObject getObject() {
189
211
190
212
@ Override
191
213
public JsonArray getArray () {
214
+ ensureTokenIsCurrent ();
192
215
if (valueParser == null ) {
193
216
valueParser = new JsonValueParser ();
194
217
}
218
+ if (parser .currentToken () != JsonToken .START_ARRAY ) {
219
+ throw new IllegalStateException ("Unexpected token " + parser .currentToken () +
220
+ " at " + parser .getTokenLocation ());
221
+ }
195
222
try {
196
223
return valueParser .parseArray (parser );
197
224
} catch (IOException e ) {
@@ -201,6 +228,7 @@ public JsonArray getArray() {
201
228
202
229
@ Override
203
230
public JsonValue getValue () {
231
+ ensureTokenIsCurrent ();
204
232
if (valueParser == null ) {
205
233
valueParser = new JsonValueParser ();
206
234
}
@@ -213,6 +241,7 @@ public JsonValue getValue() {
213
241
214
242
@ Override
215
243
public void skipObject () {
244
+ ensureTokenIsCurrent ();
216
245
if (parser .currentToken () != JsonToken .START_OBJECT ) {
217
246
return ;
218
247
}
@@ -238,6 +267,7 @@ public void skipObject() {
238
267
239
268
@ Override
240
269
public void skipArray () {
270
+ ensureTokenIsCurrent ();
241
271
if (parser .currentToken () != JsonToken .START_ARRAY ) {
242
272
return ;
243
273
}
0 commit comments