Skip to content

Commit 1d4fa88

Browse files
committed
Expose JacksonCodec private parse methods.
Motivation: Parsing a vertx structure from a Jackson JsonParser should be a possible thing. Changes: Expose the parseObject/parseArray/parseAny private methods.
1 parent fbe4c82 commit 1d4fa88

File tree

2 files changed

+87
-10
lines changed

2 files changed

+87
-10
lines changed

vertx-core/src/main/java/io/vertx/core/json/jackson/JacksonCodec.java

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeEx
220220
JsonToken remaining;
221221
try {
222222
parser.nextToken();
223-
res = parseAny(parser);
223+
res = parseValue(parser);
224224
remaining = parser.nextToken();
225225
} catch (IOException e) {
226226
throw new DecodeException(e.getMessage(), e);
@@ -233,12 +233,19 @@ public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeEx
233233
return cast(res, type);
234234
}
235235

236-
private static Object parseAny(JsonParser parser) throws IOException, DecodeException {
236+
/**
237+
* Parse a JSON value given the {@code parser}, consuming the current parser token and possibly more
238+
* when parsing an object or an array.
239+
*
240+
* @param parser the parser
241+
* @return the parsed value as an object
242+
*/
243+
public static Object parseValue(JsonParser parser) throws IOException, DecodeException {
237244
switch (parser.currentTokenId()) {
238245
case JsonTokenId.ID_START_OBJECT:
239-
return parseObject(parser);
246+
return internalParseObject(parser);
240247
case JsonTokenId.ID_START_ARRAY:
241-
return parseArray(parser);
248+
return internalParseArray(parser);
242249
case JsonTokenId.ID_STRING:
243250
return parser.getText();
244251
case JsonTokenId.ID_NUMBER_FLOAT:
@@ -255,21 +262,34 @@ private static Object parseAny(JsonParser parser) throws IOException, DecodeExce
255262
}
256263
}
257264

258-
private static Map<String, Object> parseObject(JsonParser parser) throws IOException {
265+
/**
266+
* Parse a JSON object given the {@code parser}, the parser current token must be {@link JsonTokenId#ID_START_OBJECT}
267+
*
268+
* @param parser the parser
269+
* @return the parsed object
270+
*/
271+
public static Map<String, Object> parseObject(JsonParser parser) throws IOException {
272+
if (parser.currentTokenId() != JsonTokenId.ID_START_OBJECT) {
273+
throw new DecodeException("Expecting the current parser token to be the start of an object");
274+
}
275+
return internalParseObject(parser);
276+
}
277+
278+
private static Map<String, Object> internalParseObject(JsonParser parser) throws IOException {
259279
String key1 = parser.nextFieldName();
260280
if (key1 == null) {
261281
return new LinkedHashMap<>(2);
262282
}
263283
parser.nextToken();
264-
Object value1 = parseAny(parser);
284+
Object value1 = parseValue(parser);
265285
String key2 = parser.nextFieldName();
266286
if (key2 == null) {
267287
LinkedHashMap<String, Object> obj = new LinkedHashMap<>(2);
268288
obj.put(key1, value1);
269289
return obj;
270290
}
271291
parser.nextToken();
272-
Object value2 = parseAny(parser);
292+
Object value2 = parseValue(parser);
273293
String key = parser.nextFieldName();
274294
if (key == null) {
275295
LinkedHashMap<String, Object> obj = new LinkedHashMap<>(2);
@@ -283,14 +303,27 @@ private static Map<String, Object> parseObject(JsonParser parser) throws IOExcep
283303
obj.put(key2, value2);
284304
do {
285305
parser.nextToken();
286-
Object value = parseAny(parser);
306+
Object value = parseValue(parser);
287307
obj.put(key, value);
288308
key = parser.nextFieldName();
289309
} while (key != null);
290310
return obj;
291311
}
292312

293-
private static List<Object> parseArray(JsonParser parser) throws IOException {
313+
/**
314+
* Parse a JSON array given the {@code parser}, the parser current token must be {@link JsonTokenId#ID_START_ARRAY}
315+
*
316+
* @param parser the parser
317+
* @return the parsed array
318+
*/
319+
public static List<Object> parseArray(JsonParser parser) throws IOException {
320+
if (parser.currentTokenId() != JsonTokenId.ID_START_ARRAY) {
321+
throw new DecodeException("Expecting the current parser token to be the start of an array");
322+
}
323+
return internalParseArray(parser);
324+
}
325+
326+
private static List<Object> internalParseArray(JsonParser parser) throws IOException {
294327
List<Object> array = new ArrayList<>();
295328
while (true) {
296329
parser.nextToken();
@@ -300,7 +333,7 @@ private static List<Object> parseArray(JsonParser parser) throws IOException {
300333
} else if (tokenId == JsonTokenId.ID_END_ARRAY) {
301334
return array;
302335
}
303-
Object value = parseAny(parser);
336+
Object value = parseValue(parser);
304337
array.add(value);
305338
}
306339
}

vertx-core/src/test/java/io/vertx/tests/json/JacksonTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
package io.vertx.tests.json;
1313

14+
import com.fasterxml.jackson.core.JsonParser;
15+
import com.fasterxml.jackson.core.JsonTokenId;
1416
import io.vertx.core.json.DecodeException;
1517
import io.vertx.core.json.EncodeException;
1618
import io.vertx.core.json.JsonArray;
@@ -20,6 +22,9 @@
2022
import org.junit.Assert;
2123
import org.junit.Test;
2224

25+
import java.util.Arrays;
26+
import java.util.Map;
27+
2328
import static com.fasterxml.jackson.core.StreamReadConstraints.*;
2429
import static org.junit.Assert.assertEquals;
2530
import static org.junit.Assert.assertNotNull;
@@ -134,4 +139,43 @@ private static JsonObject testMaxNameLength(int len) {
134139
String json = "{\"" + "a".repeat(len) + "\":3}";
135140
return new JsonObject(json);
136141
}
142+
143+
@Test
144+
public void testParseMap() throws Exception {
145+
JsonParser parser = JacksonCodec.createParser("{\"nested\":{\"key\":\"value\"},\"another\":4}");
146+
assertEquals(JsonTokenId.ID_START_OBJECT, parser.nextToken().id());
147+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
148+
assertEquals(JsonTokenId.ID_START_OBJECT, parser.nextToken().id());
149+
Map<String, Object> nested = JacksonCodec.parseObject(parser);
150+
assertEquals(Map.of("key", "value"), nested);
151+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
152+
assertEquals(JsonTokenId.ID_NUMBER_INT, parser.nextToken().id());
153+
assertEquals(JsonTokenId.ID_END_OBJECT, parser.nextToken().id());
154+
}
155+
156+
@Test
157+
public void testParseAny() throws Exception {
158+
JsonParser parser = JacksonCodec.createParser("{\"nested\":{\"key\":\"value\"},\"another\":4}");
159+
assertEquals(JsonTokenId.ID_START_OBJECT, parser.nextToken().id());
160+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
161+
assertEquals(JsonTokenId.ID_START_OBJECT, parser.nextToken().id());
162+
Object nested = JacksonCodec.parseValue(parser);
163+
assertEquals(Map.of("key", "value"), nested);
164+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
165+
assertEquals(JsonTokenId.ID_NUMBER_INT, parser.nextToken().id());
166+
assertEquals(JsonTokenId.ID_END_OBJECT, parser.nextToken().id());
167+
}
168+
169+
@Test
170+
public void testParseArray() throws Exception {
171+
JsonParser parser = JacksonCodec.createParser("{\"nested\":[0,1,2],\"another\":4}");
172+
assertEquals(JsonTokenId.ID_START_OBJECT, parser.nextToken().id());
173+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
174+
assertEquals(JsonTokenId.ID_START_ARRAY, parser.nextToken().id());
175+
Object nested = JacksonCodec.parseArray(parser);
176+
assertEquals(Arrays.asList(0, 1, 2), nested);
177+
assertEquals(JsonTokenId.ID_FIELD_NAME, parser.nextToken().id());
178+
assertEquals(JsonTokenId.ID_NUMBER_INT, parser.nextToken().id());
179+
assertEquals(JsonTokenId.ID_END_OBJECT, parser.nextToken().id());
180+
}
137181
}

0 commit comments

Comments
 (0)