有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

将动态JSON值解析为Java对象

在我的应用程序中,我有很多具有排序和筛选功能的概述(表)。由于不同的列可以容纳不同的值类型(字符串、数字、日期、集合等),因此这些列的过滤器也可以带来不同的值。让我向您展示几个示例(已转换为JSON,并通过REST请求发送到服务器):

对于简单字符串值,它类似于:

{"<column_name>":"<value>"}

对于数字和日期列,筛选器如下所示:

{"<column_name>":[{"operator":"eq","value":"<value>"}]}
{"<column_name>":[{"operator":"eq","value":"<value1>"},{"operator":"gt","value":"<value2>"}]}

对于设置,过滤器如下所示

{"<column_name>":["<value1>","<value2>"(,...)]}

现在,我需要在将构建SQL查询的WHERE子句的助手类中解析该JSON。在PHP中,这不是问题,因为我可以调用json_decode,然后简单地检查某个值是arraystring还是其他任何值。。。但是如何在Java中简单地做到这一点呢

到目前为止,我正在使用Spring的JsonJsonParser(我没有发现Spring类的JacksonGson和其他解析器之间有任何明显的差异)

我曾考虑创建一个自己的数据对象类,使用三个不同的构造函数,或者为所有三种可能性创建三个数据对象类,但我不知道如何处理解析器解析JSON后为column_name返回的

简单地看一下这些例子,它给了我三种可能性:

  1. Map<String, String>
  2. Map<String, Map<String, String>>
  3. Map<String, String[]>

有什么想法或线索吗


共 (2) 个答案

  1. # 1 楼答案

    Jackson的ObjectMapper treeToValue应该能够帮助您

    http://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/ObjectMapper.html#treeToValue%28com.fasterxml.jackson.core.TreeNode,%20java.lang.Class%29

    您的主要问题是JSON的第一个版本与其他两个版本的构造不同。选择另外两个,您可以像您所说的那样将JSON反序列化为Map<String, Map<String, String>,但第一个版本符合映射

    您可以使用以下几种解决方案:

    • 将JSON格式更改为始终匹配Map<String, Map<String, String>模式
    • 首先将JSON解析为JsonNode,检查值的类型并将整个内容反序列化为正确的映射模式
    • (又快又脏)您不更改JSON,但使用其中一个映射模式try,捕获JsonProcessingException,然后使用另一个映射模式重试
  2. # 2 楼答案

    您必须在运行时检查值的类型。您可以使用Map<String, Object>JsonNode

    地图<;字符串,对象>

    JsonParser parser = JsonParserFactory.getJsonParser();
    Map<String, Object> map = parser.parseMap(str);
    Object filterValue = filter.get("<column_name>");
    if (filterValue instanceof String) {
      // str is like "{\"<column_name>\":\"<value>\"}"
    } else if (filterValue instanceof Collection) {
      for (Object arrayValue : (Collection<Object>) filterValue) {
        if (arrayValue instanceof String) {
          // str is like "{\"<column_name>\":[\"<value1>\",\"<value2>\"]}"
        } else if (arrayValue instanceof Map) {
          // str is like "{\"<column_name>\":[{\"operator\":\"eq\",\"value\":\"<value>\"}]}"
        }
      }
    }
    

    JsonNode

    ObjectMapper mapper = new ObjectMapper();
    JsonNode filter = mapper.readTree(str);
    JsonNode filterValue = filter.get("<column_name>");
    if (filterValue.isTextual()) {
      // str is like "{\"<column_name>\":\"<value>\"}"
    } else if (filterValue.isArray()) {
      for (JsonNode arrayValue : filterValue.elements()) {
        if (arrayValue.isTextual()) {
          // str is like "{\"<column_name>\":[\"<value1>\",\"<value2>\"]}"
        } else if (arrayValue.isObject()) {
          // str is like "{\"<column_name>\":[{\"operator\":\"eq\",\"value\":\"<value>\"}]}"
        }
      }
    }