当前位置: 首页 > 知识库问答 >
问题:

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

宋明亮
2023-03-14

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

目标是学习如何处理JSON并捕获我想要的信息。现在,我想要完成的是以下内容:
1)我在这里发布的JSON有很多数据。跟随这个JSON的Java程序是我试图处理这个JSON,特别是,捕获“Part1/MyAnalysis/Matches”下的“name”:US SSN“元素,以及”name“:MasterCard Credit Card Number”,这两个元素都属于“Part1/MyAnalysis/Matches.”的范围。

好的,现在,我的目标是:我只想让我的程序编译并至少打印出我感兴趣的两个元素(前面提到的)。

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

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如下所示。如果有人能指出如何使这个程序编译然后打印出我想要的元素。这将是一个伟大的2步过程任务。

{
    "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();

              } 

        }
}

谢谢你的帮助。

共有1个答案

阎阎宝
2023-03-14

要考虑两件事:

  • 如果要保持流,调用jp.readvalueastree()不是一个好主意,因为这样会分配内存来创建当前节点下所有数据的树(在代码中,所有数据都在“matches”下),除非您确定这是一个小树。
  • 要获得数组中的值,不需要先创建数组。流式API将允许您在数组中遍历所需的值。

正如@Mchaker在他的回答中所示,如果您需要JSON文件中提供的大部分数据,创建一个模型来保存数据将是有益的。但如果你只是需要一些价值观,Jackson会让你这么做的。尽管如此,我必须承认,以真正的流式方式获取数据将需要一些创造性的方法来跟踪您所处的位置和您期望的数据。

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

}
 类似资料:
  • 问题内容: 有以下格式的JSON结果,JSON Lint将其显示为“有效响应”。 我的问题是:由于“ 141”,“ 8911”等都是动态值,我如何访问“ question_mark”的内容? 我的示例代码用于访问“产品”的价值。 我的问题标题“动态键”可能是错误的,但目前我不知道该问题的最佳名称是什么。 任何帮助将不胜感激! 问题答案: 使用JSONObject keys()获取密钥,然后迭代每个

  • 问题内容: 我有以下格式的JSON结果,JSON Lint将其显示为“有效响应”。 我的问题是:由于“ 141”,“ 8911”等都是动态值,我如何访问“ question_mark”的内容? 我的示例代码用于访问“产品”的价值。 JSON: 我的问题标题“动态键”可能是错误的,但目前我不知道该问题的最佳名称是什么。 任何帮助将不胜感激! 问题答案: 使用JSONObject keys() 获取密

  • 问题内容: http://play.golang.org/p/f6ilWnWTjm 我正在尝试解码以下字符串,但仅获取空值。 如何在Go中解码嵌套的JSON结构? 我想将以下内容转换为地图数据结构。 问题答案: 在Go中使用嵌套结构来匹配JSON中的嵌套结构。 这是一个如何处理示例JSON的示例: 游乐场链接 您还可以对内部结构使用匿名类型: 游乐场链接 或外部和内部结构: 游乐场链接 如果您不知

  • 问题内容: 我们的团队决定使用Retrofit 2.0, 并且我正在对该库进行一些初步研究。如标题中所述,我想通过Android应用中的Retrofit 2.0解析一些嵌套的JSON对象。 例如,这是一个嵌套的JSON对象,其格式为: 我对数组内的JSON对象感兴趣。我注意到有一些关于通过Retrofit 1.X解析嵌套JSON对象的文章,但是最新的Retrofit 2.0API发生了很大变化,这

  • 问题内容: 此JSON输出来自MongoDB聚合查询。我本质上需要将嵌套数据JSON解析为以下’ 和值。 我尝试了5种不同的技术来从中获得所需的信息,但是使用和模块却遇到了问题。 理想情况下,输出将是这样的: 问题答案: 注意:来自MongoDB的JSON响应实际上无效。JSON需要双引号(),而不是单引号()。 我不确定为什么您的响应中有单引号而不是双引号,但是从其外观上,您可以替换它们,然后只

  • 问题内容: 我正在尝试解析这种结构:(它使我发疯,并且我尝试了我能想到的一切。但是我不是很有经验) “ topDrop”就像文件名吗?player是一个JSONArray,包含5个播放器JSONObject。但是在JSON术语中,最重要的是什么。我在JSON验证程序上签出有效的凭证,我需要这样的凭证: topDrop作为JSONObject Player,作为JSONArray,并循环遍历数组中的