I am getting API response on the following format. I am working on Android project
{
Course: [
{
"Year": 2017,
"CourseTitle": "..",
"Quarter": "autumn",
},
{
"Year": 2017,
"CourseTitle": "..",
"Quarter": "autumn",
}
],
Instructor: {
"name": ,
"address":
}
}
My goal is to get Course array of courses, and assign it to the POJO (plain old java object) that I created using online tool. I am also using the GSON library. I did find different implementation online, and I finally used this, and I was able to filter the nested object "Courses", which holds an array object of courses.
JsonParser parser = new JsonParser();
JsonObject element = (JsonObject)parser.parse(response);
JsonElement responseWrapper = element.getAsJsonArray("Courses");
When I look responseWrapper using debugger tool, it holds a JSON array of course (objects). I wanted to assign these data to the "Course" POJO class I created
public class Course implements Parcelable {
private String href;
private int year;
private String courseTitle;
private String quarter;
private String courseTitleLong;
private String curriculumAbbreviation;
private String courseNumber;
}
I added the following line.
Course[] courseList = gson.fromJson(responseWrapper,Course[].class);
CourseList is an array of Course object, but when I look what I got using debugger tool all the field variables are "null". How could I solve this problem? Is there a better way I should have approached? The whole purpose is getting array of course objects so I could manipulate it for display.
Try to rename your fields to exactly match the json response, even case-wise.
Related
I am working on a big json output file which is coming as response but I want to parse only some of the fields in my logic.
For ex: The JSON looks like this
{
"lastName":"Smith",
"address":{
"streetAddress":"21 2nd Street",
"city":"New York",
"state":"NY",
"postalCode":10021
},
"age":25,
"phoneNumbers":[
{
"type":"home", "number":"212 555-1234"
},
{
"type":"fax", "number":"212 555-1234"
}
],
"firstName":"John"
}
I have created the necessary JAVA classes and mapping the JSON Object to Java object using GSON. Since, the above JSON is just a sample one in my case I have big one which is generating around 15 classes.
Currently i have to create following classes files:
- Employee.class
- Address.class
- PhoneNumber.class
I want to avoid creating PhoneNumber.class and its nested class using GSON.
Basically My query is like in above json I don't want phoneNumbers and its internal objects so how can i ignore those fields so that i have to construct less Java Class files and still it is mapped to Java Object.
So I want to avoid making classes for PhoneNumbers fields and the nested fields inside PhoneNumbers.
As suggested, Employee and Address classes are all you need:
public class Employee {
private String firstName, lastName;
private int age;
private Address address;
}
public class Address {
private String streetAddress, city, state;
private int postalCode;
}
new Gson().fromJson(json, Employee.class);, where json is the raw JSON string, should then do what you want. Without sharing your code, it is hard to tell why it doesn't work for you.
I have an Abstract class with many concrete implementations:
public abstract Ticket {
private Long id;
private Currency fine;
...
}
public class SpeedingTicket extends Ticket {
public Currency getFine(){
// Expensive!
...
}
}
public class ParkingTicket extends Ticket {
public Currency getFine(){
// Eh, not so bad
...
}
}
When the concrete classes are serialized into JSON, it is wrapped with the classes simple name (speedingTickets or parkingTickets):
"_embedded": {
"speedingTickets" :
[{
"id":1,
"fine": "$190",
...,
},
{
"id":2,
"fine": "$100",
...,
}]
}
or
"_embedded": {
"parkingTickets" :[{
"id":100,
"fine": "$15",
...,
}]
}
Since I do not know, at runtime, which Ticket implementation I am receiving back, how can I parse the JSON out using the JSON Response API given the array is wrapped with the concrete implementations simple name?
I have a hack where I take the String value of the JSON and do String operations (substring, indexOf, etc) on it to return only what's in between the braces ("[...]"). I know there's a better way to do this...
After some research, I think I'll try the following tomorrow to see if it works:
JsonNode rootNode = mapper.readTree(jsonResponse);
String classImpl = Iterables.get(rootNode.get("_embedded").fields(), 0).textValue()
I can then say List<Ticket> tickets = response.readAsList(jsonResponse, "_embedded",classImpl) which should allow me to parse the JSON into a List
If you're using Jackson (as your tag suggests), you want to use Polymorphic Deserialization - which is exactly the problem of knowing how to deserialize to the correct subtype.
For example:
#JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="#class")
class { }
What this essentially does is include the class name in your JSON, so the deserializer has enough information to properly choose the subclass to instantiate. Something like this:
"_embedded": {
"parkingTickets" :[{
"_type": "ParkingTicket.class",
"id":100,
"fine": "$15",
...,
}]
}
You can just check the type by checking the variable the response contains.
JSONObject jsonObj = new JSONObject(response);
if(jsonObj.has("speedingTickets")){
// parse speedingTickets
}else if(jsonObj.has("parkingTickets")){
// parse parkingtickets
}
A JSON object is an unordered set of key/value pairs. A JSON array is an ordered collection of values. The values themselves could be objects or arrays.
In java it is easy to parse json with org.json library https://github.com/stleary/JSON-java
Short example how to parse json array:
String str = "{ \"number\": [3, 4, 5, 6] }";
JSONObject obj = new JSONObject(str);
JSONArray arr = obj.getJSONArray("number");
for (int i = 0; i < arr.length(); i++)
System.out.println(arr.getInt(i));
I am trying to parse the JSON from this link: https://api.guildwars2.com/v2/items/56 , everything fine until i met the line: "infix_upgrade":{"attributes":[{"attribute":"Power","modifier":4},{"attribute":"Precision","modifier":3}]} ...
If i dont get this wrong: infix_upgradehas 1 element attributes inside him. attributes has 2 elements with 2 other inside them. Is this a 2 dimension array?
I have tried (code too long to post):
JsonObject _detailsObject = _rootObject.get("details").getAsJsonObject();
JsonObject infix_upgradeObject = _detailsObject.get("infix_upgrade").getAsJsonObject();
JsonElement _infix_upgrade_attributesElement = infix_upgradeObject.get("attributes");
JsonArray _infix_upgrade_attributesJsonArray = _infix_upgrade_attributesElement.getAsJsonArray();
The problem is that I dont know what to do next, also tried to continue transforming JsonArray into string array like this:
Type _listType = new TypeToken<List<String>>() {}.getType();
List<String> _details_infusion_slotsStringArray = new Gson().fromJson(_infix_upgrade_attributesJsonArray, _listType);
but im getting java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT which i guess comes from the attributes...
With a proper formatting (JSONLint, for example, checks if the JSON data is valid and does the formatting, which makes the structure more clear than what the GW link gives), attributes looks actually like this:
"attributes": [
{
"attribute": "Power",
"modifier": 4
},
{
"attribute": "Precision",
"modifier": 3
}
]
So it's an array of JsonObject and each object as two key-value pairs. This is why the parser throws an error because you require that this array contains only String which is not the case.
So the actual type is:
Type _listType = new TypeToken<List<JsonObject>>(){}.getType();
The problem is that I dont know what to do next
Hold on. You are using Gson and Java is an OO language so I suggest you to create classes.
This would be easier for you to fetch the datas afterward and for the parsing since you just need to provide the class of the actual class the JSON data represents to the parser (some edge-cases could be handled by writing a custom serializer/deserializer).
The data is also better typed than this bunch of JsonObject/JsonArray/etc.
This will give you a good starting point:
class Equipment {
private String name;
private String description;
...
#SerializedName("game_types")
private List<String> gameTypes;
...
private Details details;
...
}
class Details {
...
#SerializedName("infix_upgrade")
private InfixUpgrade infixUpgrade;
...
}
class InfixUpgrade {
private List<Attribute> attributes;
...
}
class Attribute {
private String attribute;
private int modifier;
...
}
and then just give the type to the parser:
Equipment equipment = new Gson().fromJson(jsonString, Equipment.class);
Hope it helps! :)
I am struggling to find a way to serialize / deserialize this JSON output to a Java class? Can anyone provide code sample?
[
{
"topic": "this is my topic"
},
[
{
"name": "John"
},
{
"age": 100
}
]
]
My current attempt uses this Javabean:
public class Test {
private String topic;
private List<Person> listOfPersons;
}
Which I try to deserialize data into using Gson:
gson.fromJson(this.json, Test[].class);
But the deserialization fails, because Gson is looking for a list of persons in the JSON, but it doesn't exist.
It doesn't seem like having an object next to an array, inside an array, is sensical. It would make sense to put things this way:
{
"topic": "this is my topic",
"listOfPersons" : [
{
"name": "John",
"age": 100
},
{
... another person
}
]
}
Then you could just have a Person class:
public class Person {
private String name;
private int age;
}
...and you could deserialize with the code you already have.
The problem here is that your JSON data is syntactically correct, but semantically ambiguous. And by that I mean, it appears to represent a polymorphic array, where each item in the array is of a different type.
In addition, the portion representing a 'person' seems to have been de-normalized horribly, where each attribute of a person is represented as a separate object in an array. Quite weird indeed. Unfortunately its really impossible to tell what types are represented just by looking at the data alone, and there are no hints provided to allow Gson to deserialize the data for you. The best you can do in this case is manually parse the information.
Test test = new Test();
JsonArray rootArray = new JsonParser().parse(jsonString);
test.setTopic(rootArray.get(0).get("topic");
Person person = new Person();
JsonArray personArray = rootArray.get(1);
person.setName(personArray.get(0).get("name"));
person.setAge(personArray.get(1).get("age"));
test.setListOfPersons(Arrays.asList(person));
I'm trying to parse some JSON containing a nested array. I'd like the array to map to a list of child objects within the parent I'm mapping. Here is the (slightly abbreviated) JSON and Java classes
JSON:
{
"id": "12121212121",
"title": "Test Object",
"media$content": [
{
"plfile$audioChannels": 1,
"plfile$audioSampleRate": 18000,
},
{
"plfile$audioChannels": 2,
"plfile$audioSampleRate": 48000,
},
{
"plfile$audioChannels": 2,
"plfile$audioSampleRate": 48000,
}
]
}
Java classes
class MediaObject {
#JsonProperty("id")
private String id;
#JsonProperty("title")
private String title;
#JsonProperty("media$Content")
private List<MediaContent> mediaContent;
... getters/setters ...
}
class MediaContent {
#JsonProperty("plfile$audioChannels")
private int audioChannels;
#JsonProperty("plfile$audioSampleRate")
private int audioSampleRate;
... getters/setters ...
}
I'd like to be able to deserialize using annotations along with the standard mapper code, i.e.
mapper.readValue(jsonString, MediaObject.class)
Everything works fine with the "id" and "title" fields, but my list of MediaContent objects always comes up null. This seems like something Jackson should be able to handle without much trouble, can anyone see what I'm doing wrong here?
The name of the json field is wrong - the attribute is not media$Content, rather media$[c]ontent. Otherwise I do not see why it will not work.