Я пишу код уровня фреймворка для реализации Vert.x, который работает как «перехватчик» до того, как все вызовы API попадут в соответствующие обработчики в своих вершинах.
Поскольку этот «перехватчик» запускается для каждого вызова API, ему необходимо обрабатывать все виды запросов Json:
{
"fname":"John",
"lname":"Cena"
}
[
{
"fname":"John",
"lname":"Cena"
},
{
"fname":"Shawn",
"lname":"Michaels"
}
]
На основе ввода я хочу решить, должен ли я анализировать requestBody как JsonObject или JsonArray. Все, что касается разбора запроса, например, заголовки, параметры запроса, параметры пути, остается прежним. Я знаю, что могу сделать что-то вроде:
public static int decideObjectOrArray(String requestBody) {
Object json = new JSONTokener(requestBody).nextValue();
if (json instanceof JSONObject) {
return 1;
}
//you have an object
else if (json instanceof JSONArray) {
return 2;
}
//you have an array
return 0;
}
Но для этого нужна следующая новая зависимость в моем pom:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
Могу ли я добиться такого же поведения, используя собственные пакеты vertx json?



Во-первых, вы должны оперировать Buffer, а не String при работе с телом.
При работе с Buffer у вас есть toJsonArray() и toJsonObject() для работы.
Хотя пропуск по буферу в поисках первого [ или { тоже допустим.
Если вас беспокоит производительность исключений (на самом деле это редкость), вы можете пропустить подход с использованием буфера.
Вы можете использовать Vert.x JsonParser для определения типа контента:
private Object parse(Buffer buffer) {
JsonParser parser = JsonParser.newParser();
AtomicReference<Object> result = new AtomicReference<>();
parser.handler(event -> {
switch (event.type()) {
case VALUE:
Object res = result.get();
if (res == null) {
result.set(event.value());
} else if (res instanceof List) {
List list = (List) res;
list.add(event.value());
} else if (res instanceof Map) {
Map map = (Map) res;
map.put(event.fieldName(), event.value());
}
break;
case START_ARRAY:
result.set(new ArrayList());
parser.objectValueMode();
break;
case START_OBJECT:
result.set(new HashMap());
parser.objectValueMode();
break;
}
});
parser.handle(buffer);
parser.end();
Object res = result.get();
if (res instanceof List) {
return new JsonArray((List) res);
}
if (res instanceof Map) {
return new JsonObject((Map<String, Object>) res);
}
return res;
}
Затем, если вы вызовете этот метод с другим типом содержимого:
parsed = jsonTest.parse(Buffer.buffer("[1,2,3]"));
System.out.println(parsed.getClass().getName() + " : " + parsed);
System.out.println();
parsed = jsonTest.parse(Buffer.buffer("{\"hello\": \"world\"}"));
System.out.println(parsed.getClass().getName() + " : " + parsed);
System.out.println();
parsed = jsonTest.parse(Buffer.buffer("\"text\""));
System.out.println(parsed.getClass().getName() + " : " + parsed);
Вы получите результат с соответствующим классом:
io.vertx.core.json.JsonArray : [1,2,3]
io.vertx.core.json.JsonObject : {"hello":"world"}
java.lang.String : text
Конечно, это всего лишь пример, вам нужно будет протестировать объект результата с помощью instanceof.
РЕДАКТИРОВАТЬ: если вы хотите избежать потокового парсера (который может быть медленнее), вы можете напрямую использовать API Джексона:
private Object parse(Buffer buffer) {
Object value;
try {
value = Json.mapper.readValue(buffer.getBytes(), Object.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (value instanceof List) {
List list = (List) value;
return new JsonArray(list);
} else if (value instanceof Map) {
Map map = (Map) value;
return new JsonObject(map);
}
return value;
}
Вы бы получили те же результаты.
РЕДАКТИРОВАТЬ 2: метод был добавлен для Buffer для анализа содержимого в формате JSON. Он будет выпущен в следующей версии Vert.x (3.7).
Дело принято. Если я работаю с буфером, мне все равно нужно выяснить, следует ли мне вызывать
toJsonArray()илиtoJsonObject(). Если ввод является объектом json, и я вызываю для негоtoJsonArray(), я получаю исключение. Точно так же, если ввод представляет собой массив json, и я вызываю для негоtoJsonObject(), я получаю исключение. Я могу справиться с этим, а затем принять решение, но это не похоже на правильный поступок.