[英]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 以适应域
在我调整了 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.