简体   繁体   English

使用 Jackson 解析 Java 中的 JSON 子集

[英]Parsing a subset of JSON in Java using Jackson

Given a Json, is it possible to use Jackson to only parse out a section of the message?给定 Json,是否可以使用 Jackson 仅解析消息的一部分? Say that the data I'm interested in is buried in a deep hierarchy of fields and I simply do not care about creating DTO classes for each and every class.假设我感兴趣的数据被埋在一个深层次的字段中,我根本不关心为每个类创建 DTO 类。

Given a very simplified scenario I'd like to model the Telephone class without knowing anything about the structure before it:鉴于一个非常简化的场景,我想在不了解之前的结构的情况下对 Telephone 类进行建模:

...{
  "firstName": "John",
  "lastName" : "doe",
  "age"      : 26,
  "address"  : {
    "streetAddress": "naist street",
    "city"         : "Nara",
    "postalCode"   : "630-0192"
  },
  "phoneNumbers": [
    {
      "type"  : "iPhone",
      "number": "0123-4567-8888"
    },
    {
      "type"  : "home",
      "number": "0123-4567-8910"
    }
  ]
}....

I'm thinking something in the terms of using json-path together with deserializing just the parts I'm interested of.我正在考虑使用 json-path 以及反序列化我感兴趣的部分。 Some pseudo:一些伪:

List<Telephone> phoneNrs = parse(".my.deep.structure.persons.phoneNumbers", List<Telephone.class>);
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree("... your JSON ...");

Using the JsonNode object you can then call get("my").get("deep").get("structure") to get the node you want.使用JsonNode对象,您可以调用get("my").get("deep").get("structure")来获取您想要的节点。

Once you got your hands on that node, a simple call to mapper.treeToValue(myDeepJsonNode, Telephone[].class) will get you your array of Telephone .一旦您掌握了该节点,只需调用mapper.treeToValue(myDeepJsonNode, Telephone[].class)获得Telephone数组。 You can get a list using a TypeReference as well.您也可以使用TypeReference获取列表。

To get to your deep JsonNode you can also use the findValue and findPath methods.要获得深层JsonNode您还可以使用findValuefindPath方法。

The Javadoc: https://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/JsonNode.html Javadoc: https : //fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/JsonNode.html

You can use JsonPath library.您可以使用JsonPath库。 With this library you can map your JsonPath output directly into POJO's.使用这个库,您可以将您的 JsonPath 输出直接映射到 POJO 中。

Pseudo:伪:

List<Telephone> phoneNrs = JsonPath.parse(json).read("$.my.deep.structure.persons.phoneNumbers", List.class);

Yes, it is possible the way you have mentioned in the Pseudo code.是的,您在伪代码中提到的方式是可能的。 "phoneNumbers" is a key and value returned can be passed on to Jackson deserialiying. “phoneNumbers”是一个键,返回的值可以传递给杰克逊反序列化。

If the response is an array of maps then you can iterate through each one of them and use the yourResponseAsJSONObject.get('phoneNumbers') method to get the value and pass it on to Jackson如果响应是一组地图,那么您可以遍历每个地图并使用yourResponseAsJSONObject.get('phoneNumbers')方法获取值并将其传递给 Jackson

or use JsonPath as mentioned by @dimas或使用@dimas 提到的 JsonPath

To do this efficiently with Jackson, use the Streaming API via the JsonParser class ( http://fasterxml.github.io/jackson-core/javadoc/2.5/com/fasterxml/jackson/core/JsonParser.html ).要使用 Jackson 有效地执行此操作,请通过 JsonParser 类 ( http://fasterxml.github.io/jackson-core/javadoc/2.5/com/fasterxml/jackson/core/JsonParser.html ) 使用 Streaming API。

This approach will allocate no additional memory and will not incur the cost of deserializing values for all of the skipped data.这种方法不会分配额外的内存,也不会产生为所有跳过的数据反序列化值的成本。 Since the code will be much longer and more difficult to read than using Jackson's ObjectMapper, only do this if profiling shows unacceptable GC activity or CPU usage during parsing.由于与使用 Jackson 的 ObjectMapper 相比,代码会更长且更难阅读,因此只有在分析过程中分析显示不可接受的 GC 活动或 CPU 使用率时才执行此操作。

You can skip all of the nodes that you are uninterested in until you hit the "phoneNumbers" key.您可以跳过所有您不感兴趣的节点,直到您按下“phoneNumbers”键。 Then you can call the readValueAs function to deserialize the array of phone number dictionaries like so readValueAs(new TypeReference<MyPhoneNumberType[]>()) .然后您可以调用readValueAs函数来反序列化电话号码字典数组,例如readValueAs(new TypeReference<MyPhoneNumberType[]>())

See also:另见:

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

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