控制JsonPath的read()方法返回的数据类型

时间:2016-11-22 17:49:10

标签: java jsonpath

我希望JsonPath始终将其解析的数据作为字符串返回。但是,JsonPath的read()方法的返回类型取决于要解析的数据的类型,因为JsonPath总是猜测数据类型是什么并返回该类型的结果。

问题是我无法知道将返回什么类型的数据,因为我只能访问我需要提供给read()函数的一组路径。这意味着我必须将返回的JsonPath数据存储在一个Object数组中,并使用包含instanceof关键字的if / else-if语句的非常难看的集合来确定数据是什么(然后将其转换为适当的类型)。

有没有人知道强制JsonPath返回字符串的方法?或者另一个人可以想到更好的工作吗?

这就是我现在正在做的事情(用Java):

ArrayList<Object> realData = JsonPath.read(dataDumpFile, current.getPath());

我想做什么:

ArrayList<String> realData = JsonPath.read(dataDumpFile, current.getPath());

docs我发现了这个:

  

在java中使用JsonPath时,了解结果中的预期类型非常重要。 JsonPath将自动尝试将结果转换为调用者期望的类型。

//Will throw an java.lang.ClassCastException    
List<String> list = JsonPath.parse(json).read("$.store.book[0].author")

//Works fine
String author = JsonPath.parse(json).read("$.store.book[0].author")

“调用者所期望的类型”是什么意思?

2 个答案:

答案 0 :(得分:5)

在JsonPath的典型用例中,库假定为we know what to expect from a path

  • 路径明确?路径是:

    • 确定是否只有一个结果,例如$..book[0]第一本书。
    • 如果可能有多个结果,则无限期,例如所有具有特定属性的书籍$..book[?(@.isbn)];返回类型可以是列表。
  • 结果应该是什么特定类型?例如,您可以期望返回类型DateList<Date>而不是ObjectList<Object>

在您的情况下,上述所有内容都无关紧要,因为您事先不知道类型,只需要将结果作为JSON字符串。

JsonPath中的默认解析器太聪明了,会将所有内容转换为漂亮的LinkedHashMap对象;但是如果你使用JacksonJsonNodeJsonProvider,你会得到JsonNode个对象的结果,并且你只有一个toString()来自JSON字符串结果。

更好的是,您可以使用JsonPath option ALWAYS_RETURN_LIST,这意味着您无需担心路径是明确的还是无限期的(无论结果是单个对象还是列表) )。

// Example from https://github.com/jayway/JsonPath#path-examples
final String json = "{\"store\": {\"book\": [{\"category\": \"reference\",\"author\": \"Nigel Rees\",\"title\": \"Sayings of the Century\",\"price\": 8.95},{\"category\": \"fiction\",\"author\": \"Evelyn Waugh\",\"title\": \"Sword of Honour\",\"price\": 12.99},{\"category\": \"fiction\",\"author\": \"Herman Melville\",\"title\": \"Moby Dick\",\"isbn\": \"0-553-21311-3\",\"price\": 8.99},{\"category\": \"fiction\",\"author\": \"J. R. R. Tolkien\",\"title\": \"The Lord of the Rings\",\"isbn\": \"0-395-19395-8\",\"price\": 22.99}],\"bicycle\": {\"color\": \"red\",\"price\": 19.95}},\"expensive\": 10}";

Configuration conf = Configuration.builder().jsonProvider(new JacksonJsonNodeJsonProvider())
        .options(Option.ALWAYS_RETURN_LIST, Option.SUPPRESS_EXCEPTIONS).build();

ArrayNode node = JsonPath.using(conf).parse(json).read("$.store.book[*]"); // indefinite
for (Object o : node) {
    System.out.println(o.toString());
}
// {"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}
// {"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}
// {"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}
// {"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}

node = JsonPath.using(conf).parse(json).read("$.store.book[0].author"); // definite
for (Object o : node) {
    System.out.println(o.toString());
}
// "Nigel Rees"

答案 1 :(得分:0)

假设这是你的JSON:

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": 10
}

不是解析整个JSON,而是可以查询并获取那些字符串值(作为路径),然后您可以轻松地遍历它们并获得您想要的内容:

Configuration conf = Configuration.builder()
     .options(Option.AS_PATH_LIST).build();

List<String> authorPathList = using(conf).parse(json).read("$..author");

这将返回作者路径列表:

["$['store']['book'][0]['author']",
"$['store']['book'][1]['author']",
"$['store']['book'][2]['author']",
"$['store']['book'][3]['author']"]

现在你可以遍历它们并获得你的价值:

for (string authorPath : authorPathList) {
    String author = JsonPath.parse(json).read(authorPath);
}