简体   繁体   English

Java FastXML JSON库:如何解析嵌套的JSON结构

[英]Java FastXML JSON library: How to parse a nested JSON structure

The following here under is a Java program I am trying out to test JSON Processing using the org.fasterxml.jackson.core and the jackson-databind libraries in a streaming manner. 下面是我正在尝试以流方式使用org.fasterxml.jackson.core和jackson-databind库测试JSON处理的Java程序。

The goal is to learn how to process JSON and capture the information I want. 目的是学习如何处理JSON并捕获所需的信息。 For now, what I want to accomplish is the following: 现在,我要完成以下任务:
1) The JSON that I post here under has a lot of data. 1)我在这里发布的JSON有很多数据。 The Java program that follows this JSON is my attempt to process this JSON and in particular, capture the "name": US SSN" element under "part1/myAnalysis/matches ." and also "name": MasterCard Credit Card number" , both elements falling under the the scope of " part1/myAnalysis/matches ." 遵循此JSON的Java程序是我尝试处理此JSON的尝试,尤其是捕获“ part1 / myAnalysis / matches“ name”:US SSN元素以及“ name”:MasterCard Credit Card number ,两者元素属于“ part1 / myAnalysis / matches ”的范围。 ONLY .

Okay, for now, My Goal is: I just want my program to compile and atleast print out those two elements (the ones aforementioned) that interest me . 好的,现在,我的目标是: 我只希望我的程序进行编译并至少打印出我感兴趣的两个元素(上述元素)

My attempt at compilation yielded the following results: 我的编译尝试产生以下结果:

Unprocessed property: type
Unprocessed property: incidentTimestamp
Unprocessed property: numOfMatches
Unprocessed property: myReport
Unprocessed property: whatSetItOffEntry
Unprocessed property: seeRestrictedIds
Unprocessed property: status
Unprocessed property: timeStamps
Unprocessed property: count

So the JSON, the program is attempting to process is as under. 因此,程序正在尝试处理的JSON如下。 If anyone can point out how to make this program compile and then print out the elements I want. 如果有人可以指出如何使该程序编译,然后打印出我想要的元素。 That will be a great 2 step process Task. 这将是一个很棒的两步过程Task。

 { "type": "ImportantIncidentInfo", "incidentTimestamp": "2014-05-15T10:09:27.989-05:00", "numOfMatches": 4, "myReport": { "docReports": { "part1/.": { "path": [ "unknown" ], "myAnalysis": { "matches": [ { "id": { "major": 1, "minor": 0 }, "name": "US SSN", "position": 13, "string": " 636-12-4567 " }, { "id": { "major": 3, "minor": 0 }, "name": "MasterCard Credit Card Number", "position": 35, "string": " 5424-1813-6924-3685 " } ] }, "cleanedUpData": [ { "startPosition": 0, "endPosition": 65, "frameContent": "" } ], "minedMetadata": { "Content-Encoding": "ISO-8859-1", "Content-Type": "text/html; charset=iso-8859-1" }, "deducedMetadata": { "Content-Type": "text/html; iso-8859-1" } }, "part2/.": { "path": [ "unknown" ], "patternAnalysis": { "matches": [ { "id": { "major": 1, "minor": 0 }, "name": "SSN", "position": 3, "string": " 636-12-4567\\r" }, { "id": { "major": 3, "minor": 0 }, "name": "MasterCard Credit Card Number", "position": 18, "string": "\\n5424-1813-6924-3685\\r" } ] }, "cleanedUpData": [ { "startPosition": 0, "endPosition": 44, "frameContent": "" } ], "minedMetadata": { "Content-Encoding": "windows-1252", "Content-Type": "text/plain; charset=windows-1252" }, "deducedMetadata": { "Content-Type": "text/plain; iso-8859-1" } } } }, "whatSetItOffEntry": { "action": "Log", "component": { "type": "aComponent", "components": [ { "type": "PatternComponent", "patterns": [ 1 ], "not": false } ], "not": false }, "ticketInfo": { "createIncident": true, "tags": [], "seeRestrictedIds": [ { "type": "userGroup", "name": "SiteMasters", "description": "Group for SiteMasters", "masters": [ "04fb02a2bc0fba" ], "members": [], "id": "04fade" } ] }, "letmeknowInfo": { "createNotification": true, "contactNames": [ "someguy@gmail.com" ] } }, "seeRestrictedIds": [ "04fade66c0" ], "status": "New", "timeStamps": [ "2014-03-15T10:09:27.989-05:00" ], "count": 1 } 

Task # 2 任务2
2) To process this JSON, I wrote the following Java program. 2)为了处理此JSON,我编写了以下Java程序。

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.core.*;

import java.io.*;

public class ParseJson {

    public static void main(String[] args) {

        try{

                // TODO Auto-generated method stub
                JsonFactory f = new MappingJsonFactory();
                //JsonParser jp = f.createJsonParser(new File(args[0]));
                JsonParser jp = f.createParser(new File("C:/somepath /in/my/eclipse/project/jsonFormattedModified.json"));


                JsonToken current;

                current = jp.nextToken();
                if (current != JsonToken.START_OBJECT) {
                  System.out.println("Error: root should be object: quiting.");
                  return;
                }

                while (jp.nextToken() != JsonToken.END_OBJECT) {
                  String fieldName = jp.getCurrentName();
                  // move from field name to field value
                  current = jp.nextToken();
                  if (fieldName.equals("matches")) {
                    if (current == JsonToken.START_ARRAY) {
                      // For each of the records in the array
                      while (jp.nextToken() != JsonToken.END_ARRAY) {
                        // read the record into a tree model,
                        // this moves the parsing position to the end of it
                        JsonNode node = jp.readValueAsTree();
                        // And now we have random access to everything in the object
                        System.out.println("Name: " + node.get("name").asText());
                        System.out.println("POS: " + node.get("pos").asText());
                      }
                    } else {
                      System.out.println("Error: records should be an array: skipping.");
                      jp.skipChildren();
                    }
                  } else {
                    System.out.println("Unprocessed property: " + fieldName);
                    jp.skipChildren();
                  }
                }                
              } catch(IOException ie) {
                  ie.printStackTrace();

              } 

        }
}

Thanks for all the help. 感谢您的所有帮助。

I suggest you use a very helpful Google API Gson to deal with serialization and deserialization easily. 我建议您使用非常有用的Google API Gson轻松处理序列化和反序列化。 So first of all, create all below classes that match your json structure . 因此,首先,创建与您的json结构匹配的所有下面的类。

Helper class: 助手类:

class Helper {
    String type;
    String incidentTimestamp;
    int numOfMatches;
    Report myReport;
    WhatSetItOffEntry whatSetItOffEntry;
    List<String> seeRestrictedIds;
    String status;
    List<String> timeStamps;
    int count;
    //getters and setters
}

Report class: 报告类别:

class Report {
    DocsReport docReports;
    //getters and setters
}

DocsReport class: DocsReport类:

class DocsReport {
    @SerializedName("part1/.")
    Part1 part1;
    Part2 part2;
    //getters and setters
}

Part1 class: 第一部分:

class Part1 {
    List<String> path;
    Analysis myAnalysis;
    List<CleanedUpData> cleanedUpData;
    MinedMetadata minedMetadata;
    DeducedMetadata deducedMetadata;
    //getters and setters
}

Analysis class: 分析类:

class Analysis {
    List<Information> matches;
    //getters and setters
}

Information class: 信息类:

class Information {
    Identifying id;
    String name;
    int position;
    String string;
    //getters and setters
}

Identifying class: 识别类别:

class Identifying {
    int major;
    int minor;
    //getters and setters
}

CleanedUpData class: CleanedUpData类:

class CleanedUpData {
    int startPosition;
    int endPosition;
    String frameContent;
    //getters and setters
}

MinedMetadata class: MinedMetadata类:

class MinedMetadata {
    @SerializedName("Content-Encoding")
    String contentEncoding;
    @SerializedName("Content-Type")
    String contentType;
    //getters and setters
}

DeducedMetadata class: DeducedMetadata类:

class DeducedMetadata {
    @SerializedName("Content-Type")
    String contentType;
    //getters and setters
}

Part2 class: Part2类:

class Part2 {
    List<String> path;
    Analysis patternAnalysis;
    CleanedUpData cleanedUpData;
    MinedMetadata minedMetadata;
    DeducedMetadata deducedMetadata;
    //getters and setters
}

WhatSetItOffEntry class: WhatSetItOffEntry类:

class WhatSetItOffEntry {
    String action;
    Component component;
    TicketInfo ticketInfo;
    LetmeknowInfo letmeknowInfo;
    //getters and setters
}

Component class: 组件类:

class Component {
    String type;
    List<ComponentData> components;
    Boolean not;
    //getters and setters
}

ComponentData class: ComponentData类:

class ComponentData {
    String type;
    List<Integer> patterns;
    Boolean not;
    //getters and setters
}

TicketInfo class: TicketInfo类:

class TicketInfo {
    Boolean createIncident;
    List<Object> tags;
    List<RestrictedIds> seeRestrictedIds;
    //getters and setters
}

RestrictedIds class: RestrictedIds类:

class RestrictedIds {
    String type;
    String name;
    String description;
    List<String> masters;
    List<Object> members;
    String id;
    //getters and setters
}

LetmeknowInfo class: LetmeknowInfo类:

class LetmeknowInfo {
    Boolean createNotification;
    List<String> contactNames;
    //getters and setters
}

Then get your two names as follow 然后得到你的两个名字如下

Gson gson = new Gson();
Helper data = gson
        .fromJson(
               new BufferedReader(
                        new FileReader(
                                "C:/somepath/in/my/eclipse/project/jsonFormattedModified.json")),
                new TypeToken<Helper>() {
                }.getType());

String name1 = data.getMyReport().getDocReports().getPart1()
        .getMyAnalysis().getMatches().get(0).getName();
String name2 = data.getMyReport().getDocReports().getPart1()
        .getMyAnalysis().getMatches().get(1).getName();

System.out.println(name1+"\n"+name2);

Output: 输出:

US SSN
MasterCard Credit Card Number

Two things to consider: 要考虑的两件事:

  • If you want to keep streaming, calling jp.readValueAsTree() is not a good idea as that will allocate memory to create the tree with all data under the current node (in your code, everything under "matches"), unless you know for sure this is a small tree. 如果要保持流式传输,则调用jp.readValueAsTree()并不是一个好主意,因为它将分配内存以创建包含当前节点下所有数据的树(在您的代码中,所有内容均在“ matches”下),除非您知道确定这是一棵小树。
  • To get to a value in an array, there is no need to create an array first. 要获得数组中的值,无需先创建数组。 The streaming API will let you walk to the value in the array you need. 流式API使您可以遍历所需数组中的值。

As @MChaker shows in his answer, if you need most of the data provided in the JSON file, creating a model to hold the data will be beneficial. 如@MChaker在他的答案中所示,如果您需要JSON文件中提供的大多数数据,则创建一个模型来保存数据将是有益的。 But if you just need a couple of values, Jackson will let you do that. 但是,如果您只需要几个价值观,杰克逊就会让您做到这一点。 Allthough, I must admit, getting data in a truly streaming fashion will require some creativity to find ways of keeping track of where you are and what data you expect. 尽管如此,我必须承认,以真正的流方式获取数据将需要一定的创造力,以找到跟踪您的位置以及期望的数据的方式。

Following code shows the easy way and the streaming way: 以下代码显示了简单的方法和流式传输方法:

import java.io.*;
import java.util.*;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;

/**
 * http://stackoverflow.com/q/30288878/3080094
 * Using jackson-databind-2.5.3 which uses
 * jackson-annotations-2.5.0 and
 * jackson-core-2.5.3
 * @author vanOekel
 */
public class JsonTest {

    public static void main(String[] args) {

        try {
            new JsonTest().getNames();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    ObjectMapper jsonMapper = new ObjectMapper();
    JsonFactory jsonFactory = new JsonFactory();

    void getNames() throws Exception {

        final String resourceName = "some.json";
        JsonNode jn;
        try (InputStream in = 
                Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName)
                ) {
            if (in == null) {
                throw new FileNotFoundException("File not found: " + resourceName);
            }
            jn = jsonMapper.readTree(in);
        } 
        findByPath(jn);

        try (InputStream in = 
                Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName)
                ) {
            if (in == null) {
                throw new FileNotFoundException("File not found: " + resourceName);
            }
            JsonParser jsonParser = jsonFactory.createParser(in);
            findInStream(jsonParser);
        } 
    }

    final String[] path = new String[] {"myReport", "docReports", "part1/.", "myAnalysis", "matches", "name"};

    void findByPath(JsonNode jn) {

        JsonNode matchesNamesNode = jn;
        for (int i = 0; i < path.length - 1; i++) {
            matchesNamesNode = matchesNamesNode.path(path[i]);
        }
        if (matchesNamesNode.isMissingNode()) {
            throw new RuntimeException("No node with names found.");
        }
        System.out.println("Tree names: " + matchesNamesNode.findValuesAsText(path[path.length - 1]));
    }

    void findInStream(JsonParser jp) throws Exception {

        int pathIndex = 0;
        List<String> names = new ArrayList<String>();
        boolean breakOnClose = false;

        while (jp.nextToken() != null) {
            final String fieldName = jp.getCurrentName();
            if (fieldName == null) {
                continue;
            }
            if (breakOnClose && fieldName.equals(path[path.length - 2])) {
                System.out.println("Stopping search at end of node " + fieldName);
                break;
            }
            if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
                continue;
            }
            // System.out.println("Field " + fieldName);
            if (pathIndex >= path.length - 1) {
                if (fieldName.equals(path[path.length - 1])) {
                    // move from field name to field value.
                    jp.nextToken(); 
                    String name = jp.getValueAsString();
                    if (name == null) {
                        throw new RuntimeException("No value exists for field " + fieldName);
                    }
                    names.add(name);
                    System.out.println("Found " + fieldName + " value: " + name);
                }
            } else if (fieldName.equals(path[pathIndex])) {
                System.out.println("Found node " + path[pathIndex]);
                pathIndex++;
                if (pathIndex >= path.length - 1) {
                    System.out.println("Looking for names ...");
                    breakOnClose = true;
                    // prevent breaking on "matches" value json-token.
                    jp.nextFieldName(); 
                }
            }
        }
        System.out.println("Streaming names: " + names);
    }

}
  String jsonRecord = "[
                 {
                   a:a,
                   b:
                     {
                      c:
                        [{d:d,e:e},{d:d1,e:e1}]
                     }
                  }
                ]";
 String value ="$.b.c[1].d";
 String str = JsonPath.read(jsonRecord, value);
 system.out.println(str);

it will print d1 它将打印d1

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

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