I have a JSON response like the following:
{
"number":"123456789101112",
"dimensions":"{\"height\":\"8.200\",\"width\":\"18.800\",\"depth\":\"9.400\"}",
"uom":"centimetre"
}
I am using the following to convert from JSON to GSON
Gson gson = new Gson();
Details details = gson.fromJson(JSONresponse, Details .class);
I want to know how to map the JSON response into my pojo class for converting this JSON to GSON and retrieving individual values.
I want to know how to access the height,width,depth from the response. This is my current Details class:
public class Details
{
private String number;
private String dimensions;
private String uom;
public void setNumber(String number){
this.number = number;
}
public String getNumber(){
return this.number;
}
public void setDimensions(String dimensions){
this.dimensions = dimensions;
}
public String getDimensions(){
return this.dimensions;
}
public void setUom(String uom){
this.uom = uom;
}
public String getUom(){
return this.uom;
}
}
I would model your POJO as:
public class Details {
private Integer number;
private Dimension dimensions; // lowercase according to Java naming conventions
private String uom;
// getters and setters
}
public class Dimension {
private String height;
private String width;
private String depth;
// getters and setters
}
Then just use your current (correct) code, and then access whichever fields you want:
Gson gson = new Gson();
Details details = gson.fromJson(JSONresponse, Details.class);
String height = details.getDimensions().getHeight();
Related
I want to convert below JSON structure to java object, Annotation bases.
What will be the pojo java class structure?
{
"Data1":{
"Name":"abc",
"Number":2
}
}
Data1 can by any string-like if it coming as data1 first time, next time it can be like "xyz".
How can we convert it using fasterxml json annotations?
class Node {
public String name;
public int number
}
class ConvertedPojo {
public Map<String, Node> attributes;
}
Since Data1 can be any string you need a map which will store all different string as key and value as json object
Class structure will be :
public class Data1{
#JsonProperty("Name")
private String name;
#JsonProperty("Number")
private int number;
public String getName() {
return name;
}
public void setName(String name) {
name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
number = number;
}
}
public class Data {
#JsonProperty("Data1")
Object data1;
public Object getData1() {
return data1;
}
public void setData1(Object data1) {
this.data1 = data1;
}
}
Take care of the variable naming convention.
Code to test:
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Data data1 = mapper.readValue("{\"Data1\":{\"Name\":\"abc\",\"Number\":2}}", Data.class);
System.out.println(mapper.writeValueAsString(data1));//{"Data1":{"Name":"abc","Number":2}}
Data data2 = mapper.readValue("{\"Data1\":\"data value\"}", Data.class);
System.out.println(mapper.writeValueAsString(data2));//{"Data1":"data value"}
}
Good morning guys!
I have a JSON strings that looks like:
{
"StatusCode":0,
"Message":null,
"ExecutionTime":0,
"ResponseData":[
{"Name":"name1","SiteId":"1234","Type":"Type1","X":"1234567","Y":"123456"},
{"Name":"Name2","SiteId":"2134","Type":"Type2","X":"1234567","Y":"1234567"},
{"Name":"Name3","SiteId":"3241","Type":"Type3","X":"1234567","Y":"1234567"},
{"Name":"Name4","SiteId":"4123","Type":"Type4","X":"123456","Y":"123456"}
]
}
I want to create an object where I can retrieve the Xand Y values.
I've been trying to use Jackson to serialize the JSON string, without success. I've created two extra classes for Jackson to use. One class for the top layer, StatusCode, Message, ExecutionTime and ResponseData which looks like
public class PL {
private Long statusCode;
private String executionTime;
private String message;
private ResponseData responseData;
public PL(){
}
public void setStatusCode(Long statusCode){
this.statusCode = statusCode;
}
public Long getStatusCode(){
return this.statusCode;
}
public void setExecutionTime(String executionTime){
this.executionTime = executionTime;
}
public String getExecutionTime(){
return this.executionTime;
}
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return this.message;
}
public void setResponseData(ResponseData responseData){
this.responseData = responseData;
}
public ResponseData getResponseData(){
return this.responseData;
}
}
Where ReponseData is returned as an object, and then I have another class for serializing ResponseData which looks like
public class ResponseData {
private String name;
private String siteId;
private String type;
private String x;
private String y;
public ResponseData(){
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setSiteId(String siteId){
this.siteId = siteId;
}
public String getSiteId(){
return this.siteId;
}
public void setType(String type){
this.type = type;
}
public String setType(){
return this.type;
}
public void setX(String x){
this.x = x;
}
public String getX(){
return this.x;
}
public void setY(String y){
this.y = y;
}
public String getY(){
return this.y;
}
}
I then create an ObjectMapper with
private final static ObjectMapper mapper = new ObjectMapper();
and try to so read the values with
ResponseData e = mapper.readValue(result.toString(), ResponseData.class);
and end up with the exception
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "StatusCode" (class MyClass.ResponseData), not marked as ignorable (5 known properties: "x", "y", "siteId", "name", "type"])
as if it can't parse the first entry, StatusMessage. Even if I remove the second class and only try to parse the first four entries where i return ResponseData as a String I still get the same exception.
To start with, in PL you should have a List<ResponseData> not a simple ResponseData attribute. As you can see, in the JSON, ResponseData is an array "ResponseData":[...] so it will be deserialized as a List. Each element of the list will be a ResponseData object as you defined it.
Then you have a case issue, you have upper cases in the JSON that you don't have in your class attributes. You can use the #JsonProperty (See API) annotation to overcome the problem, this way:
class PL {
#JsonProperty("StatusCode")
private Long statusCode;
#JsonProperty("ExecutionTime")
private String executionTime;
#JsonProperty("Message")
private String message;
#JsonProperty("ResponseData")
private List<ResponseData> responseDatas;
public PL(){
}
// getters/Setters
}
class ResponseData {
#JsonProperty("Name")
private String name;
#JsonProperty("SiteId")
private String siteId;
#JsonProperty("Type")
private String type;
#JsonProperty("X")
private String x;
#JsonProperty("Y")
private String y;
public ResponseData(){
}
// getters/Setters
}
Then read your JSON as a PL object, like this:
ObjectMapper mapper = new ObjectMapper();
PL pl = mapper.readValue(json, PL.class);
for(ResponseData rd : pl.getResponseDatas()) {
System.out.println(rd.getX());
System.out.println(rd.getY());
}
This outputs:
1234567
123456
1234567
1234567
1234567
1234567
123456
123456
It is fairly straightforward. Define your response structure using composition of classes. It is unfortunate to use capitalised fields in JSON, which out-of-the-box requires capitalised field names in the Java DTO. Still those can be easily mapped to conventional low-case names either by using the ACCEPT_CASE_INSENSITIVE_PROPERTIES modifier on the ObjectMapper or by annotating fields with corresponding names. I prefer a property on the ObjectMapper as it keeps the DTO independent of the serialisation code and this technique is used in the test below (the test is green):
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestDeserialization50386188 {
public static class Response {
public static class ResponseDataType {
public String name;
public String siteId;
public String type;
public long x;
public long y;
}
public int statusCode;
public String message;
public long executionTime;
public List<ResponseDataType> ResponseData = new ArrayList<>();
}
private static final String data = "{\"StatusCode\":0,\"Message\":null,\"ExecutionTime\":0,\"ResponseData\":[{\"Name\":\"name1\",\"SiteId\":\"1234\",\"Type\":\"Type1\",\"X\":\"1234567\",\"Y\":\"123456\"},{\"Name\":\"Name2\",\"SiteId\":\"2134\",\"Type\":\"Type2\",\"X\":\"1234567\",\"Y\":\"1234567\"},{\"Name\":\"Name3\",\"SiteId\":\"3241\",\"Type\":\"Type3\",\"X\":\"1234567\",\"Y\":\"1234567\"},{\"Name\":\"Name4\",\"SiteId\":\"4123\",\"Type\":\"Type4\",\"X\":\"123456\",\"Y\":\"123456\"}]}";
#Test
public void deserialize_response_withJackson_ok() throws IOException {
ObjectMapper mapper = new ObjectMapper()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
Response response = mapper.readValue(data, Response.class);
assertEquals(4, response.ResponseData.size());
assertEquals(1234567, response.ResponseData.get(2).x);
assertEquals(1234567, response.ResponseData.get(2).y);
}
}
You fill find the project with the executable test on this dedicated GitHub repo.
The "Clean Code" book by Uncle Bob does not really recommend the overuse of getters and setters so common in Java for DTOs, which a Response class is. Still you can replace all public fields with getter/setter pairs if you like but the clarity will suffer with no obvious gain on quality.
Use List to receive arrays.
private Long statusCode;
private String executionTime;
private String message;
public List<ResponseDataType> ResponseData
and it will do everything automatically.
I have a RequestModel defined as
public class RequestModel
{
public class Footage
{
public String date;
public String retrievedAt;
public String videoFileName;
public String availableUntil;
public boolean isAvailable;
}
public class People
{
public String first;
public String last;
}
public static final int USER_BLOCKED = 0;
public static final int USER_ACTIVE = 1;
public static final int USER_WAIT_PIN = 2;
public String _id;
public String status;
public String submittedAt;
public Footage footage;
public People teacher;
public People student;
public ArrayList<MessageModel> messages = new ArrayList<MessageModel>();
public boolean isExpanded = false;
public RequestModel()
{
}
My MessageModel is defined as
public class MessageModel
{
public String _id;
public String statusMessage;
public String submittedAt;
public RequestModel request;
public String status;
public String timestamp;
public boolean isExpanded = false;
public MessageModel()
{
}
}
I have an api call that pulls a single "RequestModel" item. However the messages list in that api call has "request" as a String instead of "RequestModel" object.
Is there any way i can make it parse as a different name or omit it entirely to bypass exceptions causing because of different types.
Use the annotation #SerializedName("") before declaring member to give it a substitute name
ex,
if you json looks like this
{
name:"",
age:0,
items:[...]
}
but your model class have the fields,
class User{
String name;
int age;
Data userItems[];
}
The field userItems in model is named items in the json,
you need to use that annotation on the field:
class User{
String name;
int age;
#SerializedName("items")
Data userItems[];
}
this way GSON will map items to userItems.
I have a JSON string that comes from a WFC service. When I try to convert JSON array into List object, I've got the following error :
".JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: java.io.StringReader#41f27f18; line: 1, column: 1]"
The Java class (Card Class):
public class Card {
public String ID;
public String CompanyID;
public String CompanyName;
public String FiscalCode;
public String Limit;
public String StateID;
public String CardState;
public String Deleted;
public String Sold;
public String StartDate;
public String InvoiceStartDate;
public String Quantity;
public String Value;
public String CardTypeID;
public String CardType;
public String SoldChanged;
public String DriverName;
public String VehiclePlateNumber;
public String VehicleID;
public String Discount;
public String ContractID;
public String DiscountPerMonth;
public String ProductID;
public String ProductStateID;
public String Mail;
public String WithoutLimit;
public String ContractSold;
public String ContractLimit;
public String NumberOfTransactions;
public String DriverNameOnly;
public String DriverSurnameOnly;
}
The Java code to deserialize :
strResponse = responseHandler.handleResponse(response);
if (strResponse.contains("Credit") || strResponse.contains("Debit")) {
ObjectMapper mapper = new ObjectMapper();
strResponse= strResponse.replace("\"GetCardsResult\":", "");
userCards = mapper.readValue(strResponse, mapper.getTypeFactory().constructCollectionType(List.class, Card.class));
}
The JSON string:
{ "GetCardsResult":"[{\"ID\":3,\"CompanyID\":1155,\"CompanyName\":\"test\",\"FiscalCode\":null,\"Code\":\"1423127205\",\"Limit\":0.000,\"StateID\":1,\"CardState\":\"Activ\",\"Deleted\":false,\"Sold\":0.000,\"StartDate\":\"\/Date(1412974800000+0300)\/\",\"InvoiceStartDate\":\"\/Date(-62135596800000+0200)\/\",\"Quantity\":null,\"Value\":0.0,\"CardTypeID\":1,\"CardType\":\"Credit\",\"SoldChanged\":false,\"DriverName\":\"\",\"VehiclePlateNumber\":\"B 222 ART\",\"VehicleID\":null,\"Discount\":null,\"ContractID\":15,\"DiscountPerMonth\":null,\"ProductID\":null,\"ProductStateID\":null,\"Mail\":\"\",\"WithoutLimit\":true,\"ContractSold\":null,\"ContractLimit\":null,\"NumberOfTransactions\":null,\"DriverNameOnly\":null,\"DriverSurnameOnly\":null},{\"ID\":2881,\"CompanyID\":1155,\"CompanyName\":\"test\",\"FiscalCode\":null,\"Code\":\"test0000\",\"Limit\":125.000,\"StateID\":1,\"CardState\":\"Activ\",\"Deleted\":false,\"Sold\":132.330,\"StartDate\":\"\/Date(1436130000000+0300)\/\",\"InvoiceStartDate\":\"\/Date(-62135596800000+0200)\/\",\"Quantity\":null,\"Value\":0.0,\"CardTypeID\":1,\"CardType\":\"Credit\",\"SoldChanged\":false,\"DriverName\":\"aaa aaa\",\"VehiclePlateNumber\":\"aaa\",\"VehicleID\":null,\"Discount\":null,\"ContractID\":15,\"DiscountPerMonth\":null,\"ProductID\":null,\"ProductStateID\":null,\"Mail\":\"\",\"WithoutLimit\":true,\"ContractSold\":null,\"ContractLimit\":null,\"NumberOfTransactions\":null,\"DriverNameOnly\":null,\"DriverSurnameOnly\":null}]" }
Thanks in advance!
Try this:
try {
JSONObject jsonObject = null;
yourJSONString.replace("\\", "");
jsonObject = new JSONObject(yourJSONString);
String newJSONString = jsonObject.get("GetCardsResult").toString();
JSONArray jsonMainArr = new JSONArray(newJSONString);
//now just loop the json Array
for (int i = 0; i < jsonMainArr.length(); ++i) {
JSONObject rec = jsonMainArr.getJSONObject(i);
card.set_id(rec.get("ID").toString());
//....
}
} catch (JSONException e) {
e.printStackTrace();
}
Try to use GSON its very efficient and easy to implement, As example below will be your POJO class.
public class Post {
#SerializedName("id")
public long ID;
public String title;
public String author;
public String url;
#SerializedName("date")
public Date dateCreated;
public String body;
public List tags;
public Post() {
}
}
//Tag.java
public class Tag {
public String name;
public String url;
public Tag() {
}
}
And this will how you parse your JSON string to Object Class,
Reader reader = new InputStreamReader(content);
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("M/d/yy hh:mm a");
Gson gson = gsonBuilder.create();
List<Post> posts = new ArrayList<Post>();
posts = Arrays.asList(gson.fromJson(reader, Post[].class));
content.close();
What do you pass to the mapper - string before or after compiling the regular expression?
Did you try any external lib like Gson? Everything you need is just new Gson().fromJson(strResponse, new TypeToken<List<Card>>() {}.getType(););
I have a very basic problem.
I read though the LibGDX documentation a few times regarding JSON and Google around for an answer but it still does't work..
Basically I'm pulling json from a server like such which works as:
{"id":1,"facebook_id":"23432232","json":"{\"json\":\"test\"}"}
I have a class like this:
public class ServerJson
{
public static final String NAME = "ServerJson";
private int id;
private String facebookID;
private String json;
public ServerJson(){}
public ServerJson(int id, String facebookID, String json)
{
this.id = id;
this.facebookID = facebookID;
this.json = json;
}
public int getId() {
return id;
}
public String getFacebookID() {
return facebookID;
}
public String getJson() {
return json;
}
When I try to parse the code, it doesn't work. I get null:
String resultString = httpResponse.getResultAsString(); //{"id":1,"facebook_id":"23432232","json":"{\"json\":\"test\"}"}
Json json = new Json();
ServerJson serverJson = json.fromJson(ServerJson.class, resultString);
log(serverJson.getFacebookID()); //<< Is null.
Make sure the fields of your object class match up with the fields of the json object.