通常使用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);
}
然而,我写了一个快速的测试类来检查您的JSON解析过程中遇到了一些问题。
基本上,JSON的设计和领域的设计不匹配。因此,您可以修改JSON,也可以修改领域对象。
修改JSON以适应领域
- 在属性名称中有“-”的情况下,在jackson中无法很好地解析它们,因此需要将其删除。
- 在每个对象之前添加类名并不会有所帮助。Jackson将期望这些是属性,因此类名需要被删除或替换为属性名称。
- 为了让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());
}
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以匹配域名,因为域名在设计上似乎很合理,需要较少的自定义和强制。
然而,我承认你可能没有选择权,因此需要重新设计域名。
JSON
吗?还是必须按原样反序列化它? - Michał Ziober