Using this as a reference I have described the structure of my Json data and can grab the information as needed until I get to nest records and arrays.
Parsing a complex Json Object using GSON in Java
However my JSON data is nested several times over. For example;
{
"meetings": [
{
"meetingName": "GaryVon",
"location": "USA",
"meetingType": "P",
"meetingDate": "2016-03-25",
"weatherCondition": "FINE",
"showCode": {
"meetingCode": "A",
"scheduledType": "R"
},
"venueType": "ANI",
"showPools": [
{
"showProduct": "GaryVon",
"showStatus": "Open",
}
]
}
]
}
I have my wrapper and classes describing the format of the json data. Each class in a new java file.
public class meetingContainer {
public List<meetings> meetings;
}
Top level class
public class meetings {
private String meetingName;
private String location;
private String meetingType;
private String meetingDate;
private String weatherCondition;
private ShowCode showCode;
private String venueType;
private ShowPools[] showPools;
public String getMeetingName() { return meetingName; }
public String getLocation() { return location; }
public String getMeetingType() { return meetingType; }
public String getMeetingDate() { return meetingDate; }
public String getWeatherCondition() { return weatherCondition; }
public ShowCode getShowCode() { return showCode; }
public String getVenueType() { return venueType; }
public ShowPools[] getShowPools() { return showPools; }
}
2nd Level class
public class ShowCode {
private String meetingCode;
private String scheduledType;
public String getMeetingCode() { return meetingCode; }
public String getScheduledType() { return scheduledType; }
}
2nd Level Class
public class ShowPools {
private String showProduct;
private String showStatus;
public String getShowProduct() { return showProduct; }
public String getShowStatus() { return showStatus; }
}
I then try to parse it and grab the data which works fine until I get into nested arrays/records
Gson g = new Gson();
meetingContainer mc = g.fromJson(jsonMeetingsString, meetingContainer.class);
for(meetings m: mc.meetings){
System.out.println(m.getMeetingName()); //Result = "GaryVon"
System.out.println(m.getLocation()); //Result = "USA"
System.out.println(m.getmeetingType()); //Result = "P"
System.out.println(m.getShowCode()); //Result = "packagename.ShowCode#210366b4"
}
My question is how to I declare nested arrays/records and then call those methods from different classes i.e. Call the methods in showcode and showpools. The other post did not say how. Sorry if this is a simple answer as I'm new to java.
m.getShowCode()
This returns a reference of type ShowCode, to access inner values use the getters, for example :
m.getShowCode().getMeetingCode()
You should use a list for showPools
private List<ShowPools> showPools;
Your provided JSON string is invalid. It has one extra , -
{
"showProduct": "GaryVon",
"showStatus": "Open",
^
Answer for your question you asked in comment : m.getShowCode().getShowProduct() is invalid since showCode node has only two attributes meetingCode and scheduledType.
below code is listing all values of JSON. Let me know if it not covers your question
Gson g = new Gson();
meetingContainer mc = g.fromJson(jsonMeetingsString,
meetingContainer.class);
for (meetings m : mc.meetings) {
System.out.println("meetingName: " + m.getMeetingName());
System.out.println("location: "+ m.getLocation());
System.out.println("meetingType: "+ m.getMeetingType());
System.out.println("meetingDate: "+ m.getMeetingDate());
System.out.println("weatherConditio: "+ m.getWeatherCondition());
System.out.println("showCode->meetingCode: "+ m.getShowCode().getMeetingCode());
System.out.println("showCode->scheduledType: "+ m.getShowCode().getScheduledType());
System.out.println("venueType: "+ m.getVenueType());
for(ShowPools showPool : m.getShowPools()){
System.out.println("showPools->showProduct: "+ showPool.getShowProduct());
System.out.println("showPools->showStatus: "+ showPool.getShowStatus());
}
}
Output:
meetingName: GaryVon
location: USA
meetingType: P
meetingDate: 2016-03-25
weatherConditio: FINE
showCode->meetingCode: A
showCode->scheduledType: R
venueType: ANI
showPools->showProduct: GaryVon
showPools->showStatus: Open
Related
I am trying to build POJO for my firebase RealTime Database.
Am i doing it correctly according to my Realtime Database? Link below
detailData,detailContent,detailTitleContent,isDetail,titleContent they named the same everywhere,they just have different text in them.
public class POJO {
private String titleContent;
private String detailContent;
private String detailTitleContent;
private List<String> detailData = new ArrayList<>();
private List<String> textInfo = new ArrayList<>();
private boolean isDetail;
private boolean isList;
public POJO() {
}
public POJO(String titleContent, String detailContent, String
detailTitleContent, List<String> detailData, List<String> textInfo,
boolean isDetail, boolean isList) {
this.titleContent = titleContent;
this.detailContent = detailContent;
this.detailTitleContent = detailTitleContent;
this.detailData = detailData;
this.textInfo = textInfo;
this.isDetail = isDetail;
this.isList = isList;
}
public String getTitleContent() {
return titleContent;
}
public String getDetailContent() {
return detailContent;
}
public String getDetailTitleContent() {
return detailTitleContent;
}
public List<String> getDetailData() {
return detailData;
}
public List<String> getTextInfo() {
return textInfo;
}
public boolean isDetail() {
return isDetail;
}
public boolean isList() {
return isList;
}
}
Based on the following response (which you've provided), I'll be creating the POJO Classes
{
"datas": [{
"detailData": [{
"detailContent": "<p>LOTS of information</p>",
"detailTitleContent": "Title"
}, {
"detailContent": "<p>Lots of more information!</p>",
"detailTitleContent": "Second Title"
}],
"isDetail": false,
"titleContent": "Last Title"
}]
}
Therefore, looking at this response, you can see that your first (Let's name is "MyPojo") class will have an array of "datas" object.
public class MyPojo
{
private Datas[] datas;
public Datas[] getDatas (){
return datas;
}
public void setDatas (Datas[] datas){
this.datas = datas;
}
}
Now we have to make a model object for the "Datas":
public class Datas
{
private String isDetail;
private String titleContent;
private DetailData[] detailData;
public String getIsDetail (){
return isDetail;
}
public void setIsDetail (String isDetail){
this.isDetail = isDetail;
}
public String getTitleContent (){
return titleContent;
}
public void setTitleContent (String titleContent){
this.titleContent = titleContent;
}
public DetailData[] getDetailData (){
return detailData;
}
public void setDetailData (DetailData[] detailData){
this.detailData = detailData;
}
}
Last but not least, "DetailData" model which is another array:
public class DetailData
{
private String detailTitleContent;
private String detailContent;
public String getDetailTitleContent (){
return detailTitleContent;
}
public void setDetailTitleContent (String detailTitleContent){
this.detailTitleContent = detailTitleContent;
}
public String getDetailContent (){
return detailContent;
}
public void setDetailContent (String detailContent){
this.detailContent = detailContent;
}
}
From here, you should have a complete Pojo for your JSON response and ready to be handled. Just want to point 2 things out for your benefit:
1. I highly recommend you reading the following tutorial Android JSON Parsing Tutorial and pay close attention to the The difference between [ and { – (Square brackets and Curly brackets) section as you want to gain in-depth understanding of JSONArray and JSONObject.
2. Use JSONLint to validate your JSON response as it's helpful sometimes and also use Convert XML or JSON to Java Pojo Classes - Online tool to generate the Pojo classes based on the JSON response (I used it myself in this case). The major benefit behind this is accuracy, takes less than 1 minute to copy and implement.
Good luck and let me know if you need further assistance :)
I have json structure like this:
{
"dCharg": {
"TEXT": 1000
},
"dICharg": {
"TEXT": 1000
},
"dMaktx": {
"TEXT": "No Material description available"
},
"dStatus": {
"TEXT": "Batch is restricted"
},
"dStock": {
"TEXT": "NULL"
}
}
Java code:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.gson.Gson;
import com.Data;
public class XJson {
public static void main(String[] args) {
String json = "{ \"dCharg\":{\"TEXT\":1000},\"dICharg\":{\"TEXT\":1000},\"dMaktx\":{\"TEXT\":\"No Material description avaibalbe\"},\"dStatus\":{\"TEXT\":\"Batch is restricted\"},\"dStock\":{\"TEXT\":\"NULL\"}}";
Data data = (Data) new Gson().fromJson(json, Data.class);
}
}
Data.java:
package com;
public class Data {
private String dCharg;
private String dICharg;
private String dMaktx;
private String dStatus;
private String dStock;
public String getDCharg() {
return this.dCharg;
}
public void setDCharg(String dCharg) {
this.dCharg = dCharg;
}
public String getDICharg() {
return this.dICharg;
}
public void setDICharg(String dICharg) {
this.dICharg = dICharg;
}
}
When I run the above code, I got this error message:
Caused by: java.lang.IllegalStateException: Expected a string but was
BEGIN_OBJECT at line 1 column 14 path $.dCharg
How do I resolve this?
Your JSON says that dCharg is an object, not a String:
"dCharg":{"TEXT":1000}
If it was supposed to be a String, it would have looked like:
"dCharg":"1000"
So either the JSON is wrong, or your definition of the Data object is wrong.
How you solve this problem depends on what you have control over.
If you have control over the code that generates the JSON, then fix it appropriately.
If you only have control over the Data object, then you are going to have to change all the String variables to another object that matches the definition in the JSON.
The error is because "dCharg": {
"TEXT": 1000
} is JsonObject and your trying to parse it into a String. There are two solutions to this:
1. Either you change the Json structure as per your Java Class Data. Like this:
{
"dCharg": 1000,
"dICharg": 1000,
"dMaktx": "No Material description available",
"dStatus": "Batch is restricted",
"dStock": "NULL"
}
2. Or you change the Java Object with more nested objects to reflect your Json structure. Like this:
package com;
public class Data {
private SubData dCharg;
private SubData dICharg;
private SubData dMaktx;
private SubData dStatus;
private SubData dStock;
public SubData getDCharg() {
return this.dCharg;
}
public void setDCharg(SubData dCharg) {
this.dCharg = dCharg;
}
public SubData getDICharg() {
return this.dICharg;
}
public void setDICharg(SubData dICharg) {
this.dICharg = dICharg;
}
}
public class SubData {
private String TEXT;
public String getTEXT() {
return this.TEXT;
}
public void setTEXT(String TEXT) {
this.TEXT = TEXT;
}
}
Good luck!
Gson expects a String but finds an object instead. Look closely at your json. You have
"dCharg" : {
" TEXT" : 1000
},
...
Where { "TEXT" : 1000 } is a Json object (not a string).
Your java class on the other hand defines the field as a String.
Change your json to match your java object or vice versa. For example
{
"dCharg" : "1000",
....
}
I have JSON response which looks like that:
{
"response":[
"Some number (for example 8091)",
{
"Bunch of primitives inside the first JSONObject"
},
{
"Bunch of primitives inside the second JSONObject"
},
{
"Bunch of primitives inside the third JSONObject"
},
... (and so on)
]
}
So it's an array with first integer element and other elements are JSONObject.
I don't need integer element to be parsed. So how do I handle it using GSON?
I would solve this problem by creating a custom JsonDeserializer and registering it to your Gson instance before parsing. This custom deserializer would be set up to handle both ints and real objects.
First you need to build up a series of model objects to represent the data. Here's a template for what that might look like:
private static class TopLevel {
#SerializedName("response")
private final List<ResponseElement> elements;
private TopLevel() {
this.elements = null;
}
}
private static class ResponseInteger implements ResponseElement {
private final int value;
public ResponseInteger(int value) {
this.value = value;
}
}
private static class ResponseObject implements ResponseElement {
#SerializedName("id")
private final String id;
#SerializedName("text")
private final String text;
private ResponseObject() {
this.id = null;
this.text = null;
}
}
private interface ResponseElement {
// marker interface
}
TopLevel and ResponseObject have private constructors because they are going to let Gson set their fields using reflection, while ResponseInteger has a public constructor because we're going to manually invoke it from our custom deserializer.
Obviously you will have to fill out ResponseObject with the rest of its fields.
The deserializer is relatively simple. The json you posted contains only two kinds of elements, and we'll leverage this. Each time the deserializer is invoked, it checks whether the element is a primitive, and returns a ResponseInteger if so (or a ResponseObject if not).
private static class ResponseElementDeserializer implements JsonDeserializer<ResponseElement> {
#Override
public ResponseElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) {
return new ResponseInteger(json.getAsInt());
}
else {
return context.deserialize(json, ResponseObject.class);
}
}
}
To use this deserializer, you'll have to register it with Gson using the GsonBuilder object.
private static Gson getGson() {
return new GsonBuilder()
.registerTypeAdapter(ResponseElement.class, new ResponseElementDeserializer())
.create();
}
And that's it. Now you can use this Gson object to easily parse TopLevel objects!
public void parseJson() {
TopLevel t = getGson().fromJson(json, TopLevel.class);
for (ResponseElement element : t.elements) {
System.out.println(element);
}
}
8061
[450602: Поздравляем!]
[451700: С реакцией чата и рассуждениями Папани после рипа..]
[451578: Помним...Любим...Скорбим...<br>2107 забирает лучших]
[451371: Земля тебе пухом братишка]
[451332: Доигрался, минус 900 экзов<br><br>R I P]
[451269: ]
[451242: https://www.twitch.tv/arthas подрубка<br><br>evilpapech.ru - скидка 30% на футболки!]
[451217: ]
[451181: или так це жерстко?]
[451108: ]
I used these toString() methods, which I omitted above for brevity:
#Override
public String toString() {
return Integer.toString(value);
}
#Override
public String toString() {
return "[" + id + ": " + text + "]";
}
Try this
Gson gson = new Gson();
// Reading from a file.
Example example = gson.fromJson(new FileReader("D:\\content.json"), Example.class);
POJO
package com.example;
public class Example {
private List<Integer> response = null;
public List<Integer> getResponse() {
return response;
}
public void setResponse(List<Integer> response) {
this.response = response;
}
}
Basically this structure is the wrong format for JSON data.
You need to remove the number, or put this number as a field in the same object like the one below (call ObjectA) and consider this is an array of ObjectA.
Then everything should work well. Try the code below:
public class Response {
#SerializedName("response")
#Expose
public List<ObjectA> objectA = null;
}
public class ObjectA {
#SerializedName("value")
#Expose
public Integer value;
#SerializedName("description")
#Expose
public String description;
}
Response response = new Gson().fromJson(responseString, Response.class);
Please use below ValueObject format which doesn't parse first integer element
public class ResponseVO {
public List<Response> response = new ArrayList();
public class Response {
public final long id;
public final long from_id;
...
}
}
I'm working with a JSON file that has nested objects like this,
{
"LocId":99,
"typeId":99,
"name":"foo",
"parentId":99,
"geoCode":
{
"type":"bang",
"coordinates":
[{
"latitude":99.0,
"longitude":99.0
}]
}
}
I created a container to hold the JSON file in a class like this,
public class Location_JSON {
private LocId id;
// +getter+setter
#Override
public String toString() {
return id.toString();
}
public static class LocId {
private Long locId;
private Long typeId;
private String name;
private Long parentId;
private GeoCode geoCode;
// +getters+setters
#Override
public String toString() {
return "{\"locId\":" + locId
+ ", \"typeId\":" + typeId
+ ", \"name\":" + name
+ ", \"geoCode\":" + geoCode.toString() + "}";
}
}
public static class GeoCode {
private String type;
private Coordinates coordinates;
// +getter+setter
#Override
public String toString() {
//return "{\"type\":" + type + "}";
return "{\"type\":" + type
+ ", \"coordinates\":" + coordinates.toString() + "}";
}
}
public static class Coordinates {
private Double latitude;
private Double longitude;
// +getter+setter
#Override
public String toString() {
return "[{\"latitude\":" + latitude
+ ", \"longitude\":" + longitude + "}]";
}
}
}
To test that everything works I read in the JSON object as a string like this,
String str = "the JSON string shown above";
InputStream is = new ByteArrayInputStream(str.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
Location_JSON locations = new Gson().fromJson(br, Location_JSON.class);
System.out.println(locations.toString());
This produces a NullPointerException!
I implemented two of the Deserializer solutions found in this SO post,
Get nested JSON object with GSON using retrofit but it still created the same null error.
According to this SO post,
Java - Gson parsing nested within nested what I have should be close.
I tested my code without the nested objects i.e., I erased the nested objects from both the string and the Location_JSON container, and everything worked. So I believe this is a JSON nested object problem.
UPDATE:
If you're looking at this post I just want to point out that I accepted chengpohi's answer because it solved my initial question and chengpohi was the first to provide an answer. I did however have a second problem that I did not discover until after this question was solved. Sachin Gupta provided a working solution to my second problem. If you're using this post please check out BOTH answers down below. Thank you.
Location_JSON locations = new Gson().fromJson(br, Location_JSON.class);
it should be:
LocId locations = new Gson().fromJson(br, LocId.class);
You get NullPointerException, because your LocId have not be initiliazed. Your JSON is a object of LocId.
and your JSON:
"coordinates":
[{
"latitude":99.0,
"longitude":99.0
}]
should be:
"coordinates":
{
"latitude":99.0,
"longitude":99.0
}
As already stated in above answer, you have to use LocId class as primary one.
now for java.lang.IllegalStateException you can modify GeoCode class to use array of Coordinates class. like :
public static class GeoCode {
private String type;
private Coordinates []coordinates;
// +getter+setter
#Override
public String toString() {
return "GeoCode [type=" + type + ", coordinates=" + Arrays.toString(coordinates) + "]";
}
}
{
"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"
}
}
]
}
}
My Pojos are:
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;
}
}
I haven't use Jackson before, will really appreciate if anyone could help me in parsing the file and getting the objects.
I am trying to parse this from past two days, but didnt got any success
Usually to parse JSON with the Jackson library, you would use the ObjectMapper class like this:
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.
}
However, I wrote a quick test class to check out the parsing of your JSON and came across some issues.
Basically, the design of the JSON and the design of the domain don't match up. So you can either alter the JSON, or you can alter the domain objects.
Altering the JSON to fit the domain
The property names that have "-" in them wont parse nicely in jackson, so they will need to be removed.
Having the class name before eachof the objects isn't going to help. Jackson will expect these to be properties, so the Class names will need removing or replacing with property names.
Property names must be provided as they are in the domain objects in order for jackson to parse them. You can't just say here's an object and then start a list, the list must have a property name/
After I'd adjusted a these things in the JSON, I got it to parse with the provided domain objects. The JSON I ended up with looked like this:
{
"testSuiteInfo":{
"description":"parse"
},
"listOfTestCases":{
"testCaseData":[
{
"sequence":"sequential",
"testNumber":"2",
"testCaseFile":"testcase\\Web\\Ab.xml"
},
{
"sequence":"sequential",
"testNumber":"3",
"testCaseFile":"testcase\\Web\\BC.xml"
}
]
}
}
Here's my test method that does parse the doctored JSON above (please ignore all the escape characters)
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();
}
}
Altering the domain to fit the JSON
Firstly, the main issues is having the Class names as the property identifiers. That makes it quite difficult to work with this JSON in the usual manner. I've had to add a couple of wrapper classes to get around the class names being in the JSON.
I've added an OverallWrapper class that has a TestSuite property to cater for the TestSuite class name in the JSON.
I've also added a TestCaseDataWrapper class to cater for the TestCaseData class names in the list in the JSON.
I removed the TestCase class all together as that just became a property on one of the other classes.
Then to make the property names match up with the objects, I've used the #JsonProperty annotation.
Here are the classes after the modifications, and the ultimate parser test method that works and parses the JSON. (again, excuse all the escape characters in the JSON string)
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();
}
}
Summing up
The ultimate issue is that the domain doesn't marry up with the JSON.
Personally I prefer to change the JSON to marry up to the domain, as the domain seems to make sense in it's design and requires less customization and forcing.
However, I do accept that you may not have that choice, hence the redesign of the domain.
In this blog you can find a simple way to parse a large json file without directly using Jackson's ObjectMapper
https://www.ngdata.com/parsing-a-large-json-file-efficiently-and-easily/
With jp.skipChildren() and nested loops you can reach to your section of interest and once you are there simply break the nested loops using a label:
outerloop: while (jp.nextToken() != JsonToken.END_OBJECT) {
//...nested loops here
break outerloop;
//...closing loops
}
I copied the code for reference:
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();
}
}
}
}
From the blog:
The nextToken() call each time gives the next parsing event: start object, start field, start array, start object, …, end object, …, end array, …
The jp.skipChildren() is convenient: it allows to skip over a complete object tree or an array without having to run yourself over all the events contained in it.
All the credits go to the blog's author: Molly Galetto