Vertx выбирает jsonobject против jsonarray

Я пишу код уровня фреймворка для реализации Vert.x, который работает как «перехватчик» до того, как все вызовы API попадут в соответствующие обработчики в своих вершинах.

Поскольку этот «перехватчик» запускается для каждого вызова API, ему необходимо обрабатывать все виды запросов Json:

  1. Те, которые имеют только один JsonObject:
{
   "fname":"John",
   "lname":"Cena"
}
  1. Один с JsonArray:
    [
      {
        "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?

  • Я могу придумать еще один способ добиться этого, чтобы посмотреть на 1-й непробельный символ в requestBody и принять соответствующее решение. Но это не похоже на самый чистый способ справиться с этим.
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
0
1 813
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во-первых, вы должны оперировать Buffer, а не String при работе с телом.
При работе с Buffer у вас есть toJsonArray() и toJsonObject() для работы.
Хотя пропуск по буферу в поисках первого [ или { тоже допустим.

Дело принято. Если я работаю с буфером, мне все равно нужно выяснить, следует ли мне вызывать toJsonArray() или toJsonObject(). Если ввод является объектом json, и я вызываю для него toJsonArray(), я получаю исключение. Точно так же, если ввод представляет собой массив json, и я вызываю для него toJsonObject(), я получаю исключение. Я могу справиться с этим, а затем принять решение, но это не похоже на правильный поступок.

Tom 22.02.2019 01:33

Если вас беспокоит производительность исключений (на самом деле это редкость), вы можете пропустить подход с использованием буфера.

Alexey Soshin 22.02.2019 11:13
Ответ принят как подходящий

Вы можете использовать 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).

Другие вопросы по теме