web-dev-qa-db-ja.com

Jacksonを使用して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"
            }
         }
      ]
   }
}

私の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を使用したことがありません。誰かがファイルの解析とオブジェクトの取得を手伝ってくれると、本当に感謝しています。過去2日間からこれを解析しようとしていますが、成功しませんでした

8
kumarabhishek

通常、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に含まれるクラス名を回避するために、ラッパークラスをいくつか追加する必要がありました。

  • JSONのTestSuiteクラス名に対応するために、OverallWrapperプロパティを持つTestSuiteクラスを追加しました。

  • また、JSONのリストにあるTestCaseDataクラス名に対応するためにTestCaseDataWrapperクラスを追加しました。

  • TestCaseクラスは、他のクラスの1つのプロパティになったばかりなので、まとめて削除しました。

  • 次に、プロパティ名をオブジェクトと一致させるために、@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を変更してドメインと結合することを好みます。これは、ドメインがその設計に意味を持ち、カスタマイズや強制が少なくて済むためです。

ただし、その選択肢がない可能性があることを認めます。そのため、ドメインを再設計します。

19
Dan Temple