GSON get string from complex json - java

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! :)

Related

Create an universal java mapper for json string

I'm working on a Spring-boot project where I receive different format of Json String. My goal is to convert these Json string into an Unified Java class.
I can receive many variations of this Json:
{ "id" : "someId", "type" : "temperature", "value" : 21.0 }
For example, one variation might look like :
{ "id" : "someId", "data" : { "type": "temp", "val" : 21.0 }, "location": "here" }
So these 2 Json must be mapped into the same Java class.
I already have 2 solutions in mind :
First solution
1) Create a Specific Java Class for each Json that I may receive
2) Create a function that takes this specific object and return the Unified Java Class
Second solution
1) Create a JsonNode with the Json String
2) For each key try to match it with a field of the Unified Java Class.
But we have to take into consideration every key possible of a node like "value" or "val".
What is the best approach to solve this problem ?
I'm looking for a solution that could be easy to maintain.
Edit : I'm already using Jackson, but my problem is to map this Json object into an universal Java Class independently of the Json
Edit 2 : The Unified Java Class is a class model that already exist and it's used to store information in our database. So to push information inside our database, I have to convert each json I receive into this unified format
I can see following solutions. E.g. you use Jackson for parse JSON you could declare you custom ObjectMapper:
ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
This mapper contains additional options to ignore unknow properties.
Do you Map<String, Object> as destination class. This is magic key and it works always. Contra: you do not have json validation and have to add many constant keys to read this.
Example:
public static <T> Map<String, T> readMap(String json) throws NGPException {
if (json == null) {
return null;
}
ObjectReader reader = JSON_MAPPER.readerFor(Map.class);
MappingIterator<Map<String, T>> it = reader.readValues(json);
if (it.hasNextValue()) {
Map<String, T> res = it.next();
return res.isEmpty() ? Collections.emptyMap() : res;
}
return Collections.emptyMap();
}
Client:
Map<String, Object> map = readMap("json string");
String id = (String)map.getOrDefault("id", null);
Second way is to build one general class that contain all posiible variables. Additionnaly you have to set option to Jackson ignore unknown fields. In this case, existed fields will be used by Jackson.
Example:
public static <T> T read(String json, Class<T> clazz) throws NGPException {
return mapper.readerFor(clazz).readValue(json);
}
class Response {
private String id;
private String type;
private Double value;
private String location;
private Data data;
public class Data {
private String type;
private String temp;
private Double value;
}
}
Client:
Response response = read("json string", Response.class);
I usually use GSon from Google. It is really usefull. Check gson.fromJson(yourJsonString) in your case.
You can easy use
Gson gson = new Gson();
Data data = gson.fromJson(jsonString, Data.class);

Changing JSON array to to a pojo object array

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.

Map generic JSON object to Map interface with GSON

Given the following JSON object
{
"id": 5,
"data: { ... }
}
Is it possible to map this to the following POJO?
class MyEntity {
int id;
Map<String, Object> data;
}
Because I would like to leave the data object open ended. Is this even possible or what is a better approach to go about this? I am doing this on Android.
I don't have any idea about Android application but you can achieve it using Gson library easily.
The JSON that is used in your post is not valid. It might be a typo. Please validate it here on JSONLint - The JSON Validator
Simply use Gson#fromJson(String, Class) method to convert a JSON string into the object of passed class type.
Remember the name of instance member must be exactly same (case-sensitive) as defined in JSON string as well. Read more about JSON Field Naming
Use GsonBuilder#setPrettyPrinting() that configures Gson to output Json that fits in a page for pretty printing.
Sample code:
String json = "{\"id\": 5,\"data\": {}}";
MyEntity myEntity = new Gson().fromJson(json, MyEntity.class);
String prettyJsonString = new GsonBuilder().setPrettyPrinting().create().toJson(myEntity);
System.out.println(prettyJsonString);
output:
{
"id": 5,
"data": {}
}

Java gson arrays of arrays: java.lang.IllegalStateException

I am trying to deserialize the following JSON:
[{
"customerDetails":
{
"customer_name": "name",
"customer_email": "email"
},
"shippingD‌​etails":
{
"shipping_contact": "name",
"shipping_street": "Av:"
}
}]
Array
(
[0] => Array
(
[customerDetails] => Array
(
[customer_name] => name
[customer_email] => email
)
[shippingDetails] => Array
(
[shipping_contact] => shipname
[shipping_street] => Av:Name
)
)
)
Heres my classes:
public class Order {
private List<CustomerDetail> customerDetail;
private List<Shipping> shipping;
//getters and setters
}
public class Shipping {
private String contact;
private String street;
//getters and setters
}
public class CustomerDetail{
private String name;
private String email;
//getters and setters
}
I tried this:
Gson g = new Gson();
Order[] order = g.fromJson(new FileReader("jason"), Order[].class);
List <CustomerDetail> cd = order[0].getCustomerDetail();
System.out.println(cd.get(0).getName());
But I keep gettin either NullPointer or
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
You Java doesn't match the JSON, and the error message is telling you that you're trying to parse an object rather than an array (although, the code you show using Gson wouldn't throw the exception). I'm also not sure what the thing you show under your JSON is, because it bears no resemblance to the JSON either.
Your JSON is an array. That array contains an object (presumably you're expecting it to have many of these, but as-is it shows one). That object has two fields; customerDetails and shippingD‌​etails that each hold another object.
Your Orders class would need to be:
public class Orders {
private CustomerDetail customerDetails;
private Shipping shippingDetails;
}
(and given that it looks like that's a single order, I'd drop the plural and name the class Order)
You can then parse that JSON with Gson via:
Orders[] orders = new Gson().fromJson(myJson, Orders[].class);

How to get JSON data from an url in Java?

I have checked out many pages but most of the tutorials and script return an error code with this type of JSON output. So how would I be able to extract the data from this JSON in Java?:
[
{
"user":{"id":"1","username":"user1"},
"item_name":"item1",
"custom_field":"custom1"
},
{
"user":{"id":"2","username":"user2"},
"item_name":"item2",
"custom_field":"custom2"
},
{
"user":{"id":"3","username":"user3"},
"item_name":"item3",
"custom_field":"custom3"
}
]
If you want to use Gson, then first you declare classes for holding each element and sub elements:
public class MyUser {
public String id;
public String username;
}
public class MyElement {
public MyUser user;
public String item_name;
public String custom_field;
}
Then you declare an array of the outermost element (because in your case the JSON object is a JSON array), and assign it:
MyElement[] data = gson.fromJson (myJSONString, MyElement[].class);
Then you simply access the elements of data.
The important thing to remember is that the names and types of the attributes you declare should match the ones in the JSON string. e.g. "id", "item_name" etc.
If your trying to serialize/deserialize json in Java I would recommend using Jackson. http://jackson.codehaus.org/
Once you have Jackson downloaded you can deserialize the json strings to an object which matches the objects in JSON.
Jackson provides annotations that can be attached to your class which make deserialization pretty simple.
You could try JSON Simple
http://code.google.com/p/json-simple/
Example:
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(jsonDataString);
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject obj = (JSONObject) jsonArray.get(i);
//Access data with obj.get("item_name")
}
Just be careful to check for nulls/be careful with casting and such.

Categories

Resources