将动态JSON值解析为Java对象

问题描述:

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

In my application I have lot of overviews (tables) with sorting and filtering capabilities. And becuase the different column can hold different value type (strings, numbers, dates, sets, etc.) the filter for these columns also can bring different values. Let me show you few examples (converted to JSON already as is sent to server via REST request):

对于简单的字符串值,它就像:

For simple string value it is like:

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

对于数字和日期列,过滤器如下所示:

For number and date column the filter looks like:

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

对于设置,过滤器看起来像

For set the filter looks like

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

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

Now I need to parse that JSON within a helper class that will build the WHERE clause of SQL query. In PHP this is not a problem as I can call json_decode and then simply check whether some value is array, string or whatever else... But how to do this simply in Java?

到目前为止,我正在使用Spring的JsonJsonParser(我没有发现与Spring一起提供的不同解析器(如JacksonGson等)之间的任何可见差异).

So far I am using Spring's JsonJsonParser (I didn't find any visible difference between different parsers coming with Spring like Jackson, Gson and others).

我当时正在考虑使用三个不同的构造函数创建一个自己的数据对象类,或者针对这三种可能性创建三个数据对象类,但是我不知道如何处理返回的 value 在解析器解析了JSON之后用于column_name ...

I was thinking about creating an own data object class with three different constructors or having three data object classes for all of the three possibilities, but yet I have no clue how to deal with the value returned for column_name after the JSON is parsed by parser...

简单地看一下示例,它为我提供了三种可能性:

Simply looking on the examples it gives me three possibilities:

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

有任何想法或线索吗?

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

You'll have to check the type of the values in runtime. You can work with a Map<String, Object> or with 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>\"}]}"
    }
  }
}