簡體   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