简体   繁体   English

将动态JSON值解析为Java对象

[英]Parsing dynamic JSON values to Java objects

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): 让我向您展示一些示例(已转换为JSON,因为已通过REST请求发送到服务器):

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>"(,...)]}

Now I need to parse that JSON within a helper class that will build the WHERE clause of SQL query. 现在我需要在一个将构建SQL查询的WHERE子句的辅助类中解析该JSON。 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? 在PHP中这不是问题,因为我可以调用json_decode ,然后简单地检查一些值是arraystring还是其他任何东西......但是如何在Java中简单地执行此操作?

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). 到目前为止,我使用的是Spring的JsonJsonParser (我没有发现像JacksonGson和其他人一样使用Spring的不同解析器之间有任何明显的区别)。

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... 我正在考虑使用三种不同的构造函数创建一个自己的数据对象类,或者为这三种可能性创建三个数据对象类,但是我不知道在解析器解析JSON之后如何处理为column_name返回的 。 ..

Simply looking on the examples it gives me three possibilities: 简单地看一下这些例子,它给了我三种可能性:

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

Any idea or clue? 任何想法或线索?

Jackson's ObjectMapper treeToValue should be able to help you. 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 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

Your main problem is that the first version of you JSON is not the same construction than the two others. 您的主要问题是您的第一个版本JSON与其他两个版本的结构不同。 Picking the two others you could deserialize your JSON into a Map<String, Map<String, String> as you said but the first version fits a Map. 挑选其他两个你可以将你的JSON反序列化为Map<String, Map<String, String>如你所说,但第一个版本适合Map。

There are a couple solutions available to you : 有几种解决方案可供您使用:

  • You change the JSON format to always match the Map<String, Map<String, String> pattern 您将JSON格式更改为始终与Map<String, Map<String, String>模式匹配
  • You first parse the JSON into a JsonNode, check the type of the value and deserialize the whole thing into the proper Map pattern. 首先将JSON解析为JsonNode,检查值的类型并将整个事件反序列化为正确的Map模式。
  • (quick and dirty) You don't change the JSON, but you try with one of the Map patterns, catch JsonProcessingException, then retry with the other Map pattern (快速和脏)您不更改JSON,但try使用其中一个Map模式,捕获JsonProcessingException,然后使用其他Map模式重试

You'll have to check the type of the values in runtime. 您必须在运行时检查值的类型。 You can work with a Map<String, Object> or with JsonNode . 您可以使用Map<String, Object>JsonNode

Map<String, Object> Map <String,Object>

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 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>\"}]}"
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM