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

时间:2015-05-17 15:54:39

标签: java json jackson

以下是我正在尝试使用org.fasterxml.jackson.core和jackson-databind库以流方式测试JSON处理的Java程序。

目标是学习如何处理JSON并捕获我想要的信息。现在,我想要完成的是以下内容:
1)我在这里发布的JSON有很多数据。遵循此JSON的Java程序是我尝试处理此JSON,特别是捕获“name”:“part1 / myAnalysis / matches ”下的“US SSN”元素以及“名称“:MasterCard信用卡号”,这两个元素都属于“ part1 / myAnalysis / matches ”的范围。的 ONLY 即可。

好的,就目前而言,我的目标是: 我只想让我的程序编译并至少打印出我感兴趣的那两个元素(前面提到的那些) 。< / em>的

我的编译尝试产生了以下结果:

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

所以JSON,程序正在尝试处理如下。如果有人可以指出如何编译这个程序,然后打印出我想要的元素。这将是一个伟大的两步过程任务。

{
    "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
}

任务#2
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();

              } 

        }
}

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

我建议您使用非常有用的Google API Gson来轻松处理序列化和反序列化。首先,创建与json结构匹配的所有以下类。

助手类:

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
}

报告类:

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

DocsReport类:

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

第1部分课程:

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

分析课程:

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

信息类:

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

识别班级:

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

CleanedUpData类:

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

MinedMetadata类:

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

DeducedMetadata类:

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

第2部分课程:

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

WhatSetItOffEntry类:

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

组件类:

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

ComponentData类:

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

TicketInfo类:

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

RestrictedIds类:

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

LetmeknowInfo类:

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

然后获取以下两个名称

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);

输出:

US SSN
MasterCard Credit Card Number

答案 1 :(得分:0)

需要考虑两件事:

  • 如果你想保持流式传输,调用jp.readValueAsTree()不是一个好主意,因为它会分配内存来创建当前节点下所有数据的树(在你的代码中,所有内容都在&#34;匹配&# 34;),除非你确定这是一棵小树。
  • 要获取数组中的值,不需要先创建数组。流API将让您走到所需数组中的值。

正如@MChaker在他的回答中所示,如果你需要JSON文件中提供的大部分数据,那么创建一个模型来保存数据将是有益的。但如果你只需要几个价值观,杰克逊会让你这样做。尽管如此,我必须承认,以真正的流媒体方式获取数据需要一些创造力来找到跟踪你的位置以及你期望的数据的方法。

以下代码显示了简单方法和流媒体方式:

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);
    }

}

答案 2 :(得分:0)

  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);

它将打印d1