vertx决定jsonobject与jsonarray

时间:2019-02-20 00:02:20

标签: arrays json vert.x

我正在为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包是否可以实现相同的行为?

  • 我可以想到的另一种方法是查看requestBody中的第一个非空白字符并做出相应的决定。但是似乎并不是解决此问题的最干净的方法。

2 个答案:

答案 0 :(得分:1)

您可以使用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测试结果对象。

编辑:如果您想避免流解析器(可能会更慢),则可以直接使用Jackson 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 :从method has been addedBuffer,将内容解析为JSON。它将在下一个Vert.x版本(3.7)中发布。

答案 1 :(得分:0)

首先,在处理正文时,您应该在Buffer上进行操作,而不要在String上进行操作。
使用Buffer时,您可以使用toJsonArray()toJsonObject()
尽管跳过缓冲区搜索第一个[{也是有效的选择。