繁体   English   中英

使用 Jackson 解析 Json 文件

[英]Parsing Json File using Jackson

{
   "TestSuite":{
      "TestSuiteInfo":{
         "-description":"parse"
      },
      "TestCase":[
         {
            "TestCaseData":{
               "-sequence":"sequential",
               "-testNumber":"2",
               "-testCaseFile":"testcase\\Web\\Ab.xml"
            }
         },
         {
            "TestCaseData":{
               "-sequence":"sequential",
               "-testNumber":"3",
               "-testCaseFile":"testcase\\Web\\BC.xml"
            }
         }
      ]
   }
}

我的 Pojo 是:

public class TestSuite {    

    private TestSuiteInfo testSuiteInfo;
    private TestCase listOfTestCases;

    public TestSuiteInfo getTestSuiteInfo() {   
        return testSuiteInfo;
    }

    public void setTestSuiteInfo(TestSuiteInfo testSuiteInfo) {
        this.testSuiteInfo = testSuiteInfo;
    }

    public TestCase getListOfTestCases() {
        return listOfTestCases;
    }

    public void setListOfTestCases(TestCase listOfTestCases) {
        this.listOfTestCases = listOfTestCases;
    }
}


public class TestSuiteInfo {

    private String description;

    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
}


import java.util.Iterator;
import java.util.List;

public class TestCase {

    private List<TestCaseData> testCaseData;

    public List<TestCaseData> getTestCaseData() {
        return testCaseData;
    }

    public void setTestCaseData(List<TestCaseData> testCaseData) {
        this.testCaseData = testCaseData;
    }
}


public class TestCaseData {

    private String sequence;
    private int testNumber;
    private String testCaseFile;

    public String getSequence() {   
        return sequence;
    }

    public void setSequence(String sequence) {
        this.sequence = sequence;
    }

    public int getTestNumber() {
        return testNumber;
    }

    public void setTestNumber(int testNumber) {
        this.testNumber = testNumber;
    }

    public String getTestCaseFile() {
        return testCaseFile;
    }

    public void setTestCaseFile(String testCaseFile) {
        this.testCaseFile = testCaseFile;
    }
}

我以前没有使用过杰克逊,如果有人能帮助我解析文件并获取对象,我将不胜感激。 我试图从过去两天解析这个,但没有取得任何成功

通常要使用 Jackson 库解析 JSON,您可以像这样使用ObjectMapper类:

public static void main(final String[] args) {
    final String json = "some JSON string";
    final ObjectMapper mapper = new ObjectMapper();
    final TestSuite readValue = mapper.readValue(json, TestSuite.class);
    //Then some code that uses the readValue.
    //Keep in mind that the mapper.readValue() method does throw some exceptions
    //So you'll need to handle those too.    
}

但是,我编写了一个快速测试类来检查您的 JSON 的解析,并遇到了一些问题。

基本上,JSON 的设计和域的设计不匹配。 因此,您可以更改 JSON,也可以更改域对象。

更改 JSON 以适应域

  1. 包含“-”的属性名称在 jackson 中无法很好地解析,因此需要将其删除。
  2. 在每个对象之前都有类名不会有帮助。 Jackson 期望这些是属性,因此类名需要删除或替换为属性名。
  3. 属性名称必须在域对象中提供,以便 jackson 解析它们。 你不能只说这里是一个对象然后开始一个列表,列表必须有一个属性名/

在我调整了 JSON 中的这些东西之后,我让它用提供的域对象进行解析。 我最终得到的 JSON 如下所示:

{
   "testSuiteInfo":{
      "description":"parse"
   },
   "listOfTestCases":{
      "testCaseData":[
         {
            "sequence":"sequential",
            "testNumber":"2",
            "testCaseFile":"testcase\\Web\\Ab.xml"
         },
         {
            "sequence":"sequential",
            "testNumber":"3",
            "testCaseFile":"testcase\\Web\\BC.xml"
         }
      ]
   }
}

这是我的测试方法,它确实解析了上面修改过的 JSON(请忽略所有转义字符)

public static void main(final String[] args) {
    final String json = "{\"testSuiteInfo\":{\"description\":\"parse\"}," +
            "\"listOfTestCases\":{" +
            "\"testCaseData\":[" +
            "{\"sequence\":\"sequential\",\"testNumber\":\"2\",\"testCaseFile\":\"testcase\\\\Web\\\\Ab.xml\"}," +
            "{\"sequence\":\"sequential\",\"testNumber\":\"3\",\"testCaseFile\":\"testcase\\\\Web\\\\BC.xml\"}" +
            "]" +
            "}" +
            "}";

    final ObjectMapper mapper = new ObjectMapper();

    try {
        final TestSuite readValue = mapper.readValue(json, TestSuite.class);
        System.out.println(readValue.getListOfTestCases()); //just a test to see if the object is built
    }
    catch (final Exception e) {
        e.printStackTrace();
    }
}

更改域以适合 JSON

首先,主要问题是将类名称作为属性标识符。 这使得以通常的方式使用这个 JSON 变得非常困难。 我不得不添加几个包装类来绕过 JSON 中的类名。

  • 我添加了一个OverallWrapper类,它有一个TestSuite属性来满足 JSON 中的 TestSuite 类名称。

  • 我还添加了一个TestCaseDataWrapper类来满足 JSON 列表中的 TestCaseData 类名称。

  • 我一起删除了 TestCase 类,因为它只是成为其他类之一的属性。

  • 然后为了使属性名称与对象匹配,我使用了@JsonProperty注释。

下面是修改后的类,以及最终解析 JSON 的解析器测试方法。 (再次原谅 JSON 字符串中的所有转义字符)

import org.codehaus.jackson.annotate.JsonProperty;         

public class OverallWrapper {                              

    private TestSuite testSuite;                           

    @JsonProperty("TestSuite")                             
    public TestSuite getTestSuite() {                      
        return this.testSuite;                             
    }                                                      

    public void setTestSuite(final TestSuite testSuite) {  
        this.testSuite = testSuite;                        
    }                                                      
}



import java.util.List;                                                                                                                                  
import org.codehaus.jackson.annotate.JsonProperty;                              

public class TestSuite {                                                        

    private TestSuiteInfo testSuiteInfo;                                        

    private List<TestCaseDataWrapper> testCaseData;                             

    @JsonProperty("TestCase")                                                   
    public List<TestCaseDataWrapper> getTestCaseData() {                        
        return this.testCaseData;                                               
    }                                                                           

    public void setTestCaseData(final List<TestCaseDataWrapper> testCaseData) { 
        this.testCaseData = testCaseData;                                       
    }                                                                           

    @JsonProperty("TestSuiteInfo")                                              
    public TestSuiteInfo getTestSuiteInfo() {                                   
        return this.testSuiteInfo;                                              
    }                                                                           

    public void setTestSuiteInfo(final TestSuiteInfo testSuiteInfo) {           
        this.testSuiteInfo = testSuiteInfo;                                     
    }                                                                                                                                                   
}          



import org.codehaus.jackson.annotate.JsonProperty;          

public class TestSuiteInfo {                                

    private String description;                             

    @JsonProperty("-description")                           
    public String getDescription() {                        
        return this.description;                            
    }                                                       
    public void setDescription(final String description) {  
        this.description = description;                     
    }                                                       
}                                                                                                                                



import org.codehaus.jackson.annotate.JsonProperty;                  

public class TestCaseDataWrapper {                                  

    @JsonProperty("TestCaseData")                                   
    private TestCaseData testcaseData;                              

    public TestCaseData getTestcaseData() {                         
        return this.testcaseData;                                   
    }                                                               

    public void setTestcaseData(final TestCaseData testcaseData) {  
        this.testcaseData = testcaseData;                           
    }                                                               
}       



import org.codehaus.jackson.annotate.JsonProperty;             

public class TestCaseData {                                    

    private String sequence;                                   
    private int testNumber;                                    
    private String testCaseFile;                               

    @JsonProperty("-sequence")                                 
    public String getSequence() {                              
        return this.sequence;                                  
    }                                                          

    public void setSequence(final String sequence) {           
        this.sequence = sequence;                              
    }                                                          

    @JsonProperty("-testNumber")                               
    public int getTestNumber() {                               
        return this.testNumber;                                
    }                                                          

    public void setTestNumber(final int testNumber) {          
        this.testNumber = testNumber;                          
    }                                                          

    @JsonProperty("-testCaseFile")                             
    public String getTestCaseFile() {                          
        return this.testCaseFile;                              
    }                                                          

    public void setTestCaseFile(final String testCaseFile) {   
        this.testCaseFile = testCaseFile;                      
    }                                                          
}                                                              



public static void main(final String[] args) {

    final String json = "{\"TestSuite\":{\"TestSuiteInfo\":{\"-description\":\"parse\"},\"TestCase\":[" +
            "{\"TestCaseData\":{\"-sequence\":\"sequential\",\"-testNumber\":\"2\",\"-testCaseFile\":\"testcase\\\\Web\\\\Ab.xml\"}}," +
            "{\"TestCaseData\":{\"-sequence\":\"sequential\",\"-testNumber\":\"3\",\"-testCaseFile\":\"testcase\\\\Web\\\\BC.xml\"}}" +
            "]}}";

    final ObjectMapper mapper = new ObjectMapper();

    try {
        final OverallWrapper readValue = mapper.readValue(json, OverallWrapper.class);

        System.out.println(readValue.getTestSuite());
    }
    catch (final Exception e) {
        e.printStackTrace();
    }
}

加起来

最终的问题是域与 JSON 不匹配。

就我个人而言,我更喜欢更改 JSON 以与域结合,因为域的设计似乎很有意义,并且需要较少的定制和强制。

但是,我确实接受您可能没有那个选择,因此重新设计了域。

在此博客中,您可以找到一种无需直接使用 Jackson 的 ObjectMapper 即可解析大型 json 文件的简单方法https://www.ngdata.com/parsing-a-large-json-file-efficiently-and-easily/

使用 jp.skipChildren() 和嵌套循环,您可以到达您感兴趣的部分,一旦到达,只需使用标签打破嵌套循环:

outerloop: while (jp.nextToken() != JsonToken.END_OBJECT) {
  //...nested loops here
  break outerloop;
  //...closing loops
}

我复制了代码以供参考:

import org.codehaus.jackson.map.*;
import org.codehaus.jackson.*;

import java.io.File;

public class ParseJsonSample {
  public static void main(String[] args) throws Exception {
    JsonFactory f = new MappingJsonFactory();
    JsonParser jp = f.createJsonParser(new File(args[0]));

    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("records")) {
        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("field1: " + node.get("field1").getValueAsText());
            System.out.println("field2: " + node.get("field2").getValueAsText());
          }
        } else {
          System.out.println("Error: records should be an array: skipping.");
          jp.skipChildren();
        }
      } else {
        System.out.println("Unprocessed property: " + fieldName);
        jp.skipChildren();
      }
    }                
  }
}

来自博客:

nextToken() 每次调用都会给出下一个解析事件:起始对象、起始字段、起始数组、起始对象、……、结束对象、……、结束数组、……

jp.skipChildren() 很方便:它允许跳过完整的对象树或数组,而不必自己遍历其中包含的所有事件。

所有学分归博客作者所有: Molly Galetto

暂无
暂无

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

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