Deserialize JSON from a JSON array - java

I am using Jackson and I am trying to deserialize a JSON response that looks like the following:
{
"Warnings": [{
"Message": "Account code '48s9' has been removed as it does not match a recognised account"
},
{
"Message": "Account code '48s9' has been removed as it does not match a recognised account"
}
]
}
am I correct in saying that the class would look as follows? Is there some way this can be done?
#JsonIgnoreProperties(ignoreUnknown = true)
public class WarningsClass {
private String Message;
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
}

was able to figure it out:
// import com.fasterxml.jackson.databind.ObjectMapper; // version 2.11.1
// import com.fasterxml.jackson.annotation.JsonProperty; // version 2.11.1
/* ObjectMapper om = new ObjectMapper();
Root root = om.readValue(myJsonString), Root.class); */
public class Warning{
#JsonProperty("Message")
public String message;
}
public class WarningsClass{
#JsonProperty("Warnings")
public List<Warning> warnings;
}
WarningsClass messageResponse = mapper.readValue(data, WarningsClass.class);
something like this would work

Related

Reformat JSON arrays/object in java

I am trying to reformat this json file to a different format. I never used jackson or gson before. I get the idea of it but I don't know how to implement it.
So what I have is a json file: file.json that contains:
{
"Fruits": [
{
"name": "avocado",
"organic": true
},
{
"name": "mango",
"organic": true
}
]
}
What I want is to get in this format:
{
"List Fruits":{
"Fruits": [
{
"name": "avocado",
"organic": true
},
{
"name": "mango",
"organic": true
}
]
}
}
Somehow add the "List Fruits" in the json file.
I am trying to use the jackson api but I don't know how.
Assign the JSON to String variable, for example assign the above JSON to variable called json:
String json = "..." // here put your JSON text;
Prepare classes for your objects:
class Fruit {
private String name;
private boolean organic;
}
class Fruits {
private List<Fruit> fruits;
}
then use Gson to convert JSON to your objects:
Gson gson = new Gson();
Fruits fruits = gson.fromJson(json, Fruits.class);
Next prepare wrapper class ListOfFruits for your fruits object:
class ListOfFruits {
private Fruits listOfFruits;
public ListOfFruits(Fruits fruits) {
listOfFruits = fruits;
}
}
Next pack your fruits object into another one:
ListOfFruits lof = new ListOfFruits(fruits);
And finally generate back the output JSON:
String newJson = gson.toJson(lof);
You do not need to create POJO model for reading and updating JSON. Using Jackson, you can read whole JSON payload to JsonNode, create a Map with required key and serialising to JSON back. See below example:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.Collections;
import java.util.Map;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
JsonNode root = mapper.readTree(jsonFile);
Map<String, JsonNode> output = Collections.singletonMap("List Fruits", root);
System.out.println(mapper.writeValueAsString(output));
}
}
Above code prints:
{
"List Fruits" : {
"Fruits" : [ {
"name" : "avocado",
"organic" : true
}, {
"name" : "mango",
"organic" : true
} ]
}
}
I would highly recommend going through the documentations of Jackson or Gson libraries as you mentioned you are new.
I have created a sample git repo for this item. This sample uses Jackson API.
Visit https://github.com/rajramo61/jsonwrapper
final InputStream fileData = ClassLoader.getSystemResourceAsStream("file.json");
ObjectMapper mapper = new ObjectMapper();
InitialJson initialJson = mapper.readValue(fileData, InitialJson.class);
System.out.println(mapper.writeValueAsString(initialJson));
final FinalJson finalJson = new FinalJson();
finalJson.setListOfFruits(initialJson);
System.out.println(mapper.writeValueAsString(finalJson));
This is the Fruit class.
public class Fruit {
private String name;
private boolean organic;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getOrganic() {
return organic;
}
public void setOrganic(boolean organic) {
this.organic = organic;
}
#Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", organic=" + organic +
'}';
}
}
Here is FinalJson class detail. This is the class will wrap the initial json loaded from jsn file.
public class FinalJson {
private InitialJson listOfFruits;
#JsonProperty("List Fruits")
public InitialJson getListOfFruits() {
return listOfFruits;
}
public void setListOfFruits(InitialJson listOfFruits) {
this.listOfFruits = listOfFruits;
}
}
Here is InitialJson class detail. This is the class pulls data from json file.
public class InitialJson {
private List<Fruit> fruits;
#JsonProperty("Fruits")
public List<Fruit> getFruits() {
return fruits;
}
public void setFruits(List<Fruit> fruits) {
this.fruits = fruits;
}
#Override
public String toString() {
return "InitialJson{" +
"fruits=" + fruits +
'}';
}
}
You can fork the repo and close this in local and it should work fine.

Issue converting from JSON to POJO using Gson

I have a JSON REST endpoint response and I wanted to get the value of hotelNbr from it. How do i do it ?
{
"found": [
{
"hotelNbr": 554050442,
"hotelAddress": "119 Maven Lane, New Jersey",
}
],
"errors": []
}
I am using the below code to get it but it fails in below mentioned line:
public List<Hotel> RDS_POST_HotelDetails(String HotelName, String sUrl) throws Exception, IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
// Create your http client
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
// Create http Put object
HttpPost ohttppost = new HttpPost(sUrl);
// Message Body
StringEntity input = new StringEntity(
"{\"hotelNbr\":[\""+HotelName+"\" ]}"
);
// Set content type for post
input.setContentType("application/json");
// attach message body to request
ohttppost.setEntity(input);
// submit request and save response
HttpResponse response = httpclient.execute(ohttppost);
// Get response body (entity and parse to string
String sEntity = EntityUtils.toString(response.getEntity());
List<Hotel> hotelobject = new ArrayList<Hotel>();
// Create a type token representing the type of objects in your json response
// I had to use the full class path of TYPE because we also have a Type class in our project
java.lang.reflect.Type cType = new TypeToken<List<Hotel>>() {
}.getType();
// Convert to Array object using gson.fromJson(<json string>,
// <type>)
hotelObject = gson.fromJson(sEntity, cType); // I am getting error here
String hotelNumber = hotelObject.get(0).getFound().get(0).getItemNbr().toString();
}
Please find the Hotel.java class below
package com.hotels.company;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Hotel {
#SerializedName("found")
#Expose
private List<Found> found = null;
#SerializedName("errors")
#Expose
private List<Object> errors = null;
public List<Found> getFound() {
return found;
}
public void setFound(List<Found> found) {
this.found = found;
}
public List<Object> getErrors() {
return errors;
}
public void setErrors(List<Object> errors) {
this.errors = errors;
}
}
Please find Found.java class below :
package com.hotels.company;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Found {
#SerializedName("hotelNbr")
#Expose
private Integer hotelNbr;
#SerializedName("hotelAddress")
#Expose
private String hotelAddress;
public Integer getHotelNbr() {
return hotelNbr;
}
public void setHotelNbr(Integer hotelNbr) {
this.hotelNbr = hotelNbr;
}
public String getHotelAddress() {
return hotelAddress;
}
public void setHotelAddress(String hotelAddress) {
this.hotelAddress = hotelAddress;
}
}
I tried finding some examples in StackOverflow questions but didn't get solution for mine. Any help will be appreciated.
The JSON you are parsing is not well formatted..
There is a comma after "hotelAddress" remove that
Correct JSON would be:
{
"found":[
{
"hotelNbr":554050442,
"hotelAddress":"119 Maven Lane, New Jersey"
}
],
"errors":[ ]
}
I found a couple of issues:
Json is not valid. Observe there is a comma at the end of "hotelAddress": "119 Maven Lane, New Jersey",. Remove it.
You are trying to deserialize the json into List<Hotel>, but the json mentioned is not a list. Either update the json or deserialise it into Hotel object instead of List.

Firebase Android: how do I access params nested in data via RemoteMessage?

via this shape:
{
"to": "000",
"priority": "high",
"data": {
"title": "A Title",
"message": "A Message",
"link": {
"url": "http://www.espn.com",
"text": "ESPN",
}
}
}
how can I access "url" and "text"?
String messageLink = remoteMessage.getData().get("link");
gets me:
{"text":"ESPN","url":"http://www.espn.com"}
but how do I drill deeper?
remoteMessage.getData().get("link").get("text");
doesnt quite work... I have also attempted JSONObject:
JSONObject json = new JSONObject(remoteMessage.getData());
JSONObject link = json.getJSONObject("link");
but this gives me try catch errors...
Any help and direction as always is greatly appreciated!
I would use gson and define a model class. The remote message gives you a Map<String, String> and their is no matching constructor for creating a json object.
Add gson to your build.xml:
compile 'com.google.code.gson:gson:2.5'
Create a notification model:
import com.google.gson.annotations.SerializedName;
public class Notification {
#SerializedName("title")
String title;
#SerializedName("message")
String message;
#SerializedName("link")
private Link link;
public String getTitle() {
return title;
}
public String getMessage() {
return message;
}
public Link getLink() {
return link;
}
public class Link {
#SerializedName("url")
String url;
#SerializedName("text")
String text;
public String getUrl() {
return url;
}
public String getText() {
return text;
}
}
}
Deserialize a notification object from the remote message.
If all your custom keys are at the top level:
Notification notification = gson.fromJson(gson.toJson(remoteMessage.getData()), Notification.class);
If your custom json data is nested in a single key for example "data" then use:
Notification notification = gson.fromJson(remoteMessage.getData().get("data"), Notification.class);
Note in this simple case the #SerializedName() annotations are unnecessary since the field names exactly match the keys in the json, but if you for example have a key name start_time but you want to name the java field startTime you would need the annotation.
As simple as that:
String linkData = remoteMessage.getData().get("link");
JSONObject linkObject = new JSONObject(linkData);
String url = linkObject.getString("url");
String text = linkObject.getString("text");
Of course, together with proper error handling.
Faced this issue when migrating from GCM to FCM.
The following is working for my use case, so perhaps it will work for you.
JsonObject jsonObject = new JsonObject(); // com.google.gson.JsonObject
JsonParser jsonParser = new JsonParser(); // com.google.gson.JsonParser
Map<String, String> map = remoteMessage.getData();
String val;
for (String key : map.keySet()) {
val = map.get(key);
try {
jsonObject.add(key, jsonParser.parse(val));
} catch (Exception e) {
jsonObject.addProperty(key, val);
}
}
// Now you can traverse jsonObject, or use to populate a custom object:
// MyObj o = new Gson().fromJson(jsonObject, MyObj.class)

return any exception in json in rest api

Is there any simple methods to return exception in JSON using Rest api?
I've already googled this question, but all solutions i see, was about throwing exceptions during some calculations. But what if income parameters are wrong? I mean what if there is sone string instead of int input parameter?
I created some DTO class for input data:
#XmlRootElement
public class RequestDTO implements Serializable{
private static final long serialVersionUID = 1L;
#XmlElement(name = "request_id")
private String requestId;
#XmlElement(name = "site")
private List<String> sitesIds;
#XmlElement(name = "date_begin")
#JsonSerialize(using = DateSerializer.class)
#JsonDeserialize(using = DateDeserializer.class)
private Date dateBegin;
#XmlElement(name = "date_end")
#JsonSerialize(using = JsonDateSerializer.class)
#JsonDeserialize(using = JsonDateDeserializer.class)
private Date dateEnd;
#XmlElement(name = "volume")
private double volume;
// there is getters and setters
}
If i sent something like 'qwerty' instead of 'volume' field in my json request i'l see error message like Runtime. Is it possible to handle it in someway? I mean to return error in json with such structure?
public class ExceptionDTO {
private String shortExceptionMessage;
private String stackTrace;
public ExceptionDTO(String shotExceptionMessage, String stackTrace){
this.shortExceptionMessage = shotExceptionMessage;
this.stackTrace = stackTrace;
}
public String getShortExceptionMessage() {
return shortExceptionMessage;
}
public String getStackTrace() {
return stackTrace;
}
}
UPD1:
#Provider
#Singleton
public class ExceptionMapperProvider implements ExceptionMapper<Exception>{
#Override
public Response toResponse(final Exception e) {
StringBuilder trace = new StringBuilder();
IntStream.range(0, e.getStackTrace().length)
.forEach(i -> trace.append(e.getStackTrace()[i]).append('\n'));
ExceptionDTO exceptionMessage = new ExceptionDTO(
e.toString(),
trace.toString()
);
return Response.status(500).entity(exceptionMessage).build();
}
}
As it's not really clear if you are interested on checking if field or value of the payload is correct, here are a few ways to work with both.
If you want to check if the value for a field is correct (ie volume field value should be greater than zero etc), check out bean validation. This makes use of annotations on the fields you want to verify.
// for example
#Min(value = 0, message = "invalid message")
private double range;
To use your ExceptionDTO as error response whenever one of those validation fails, you can do so by creating an ExceptionMapper<ConstraintViolationException>. check it here for more details.
If you are checking for the invalid field (ie client sends ragne fields instead of range), have a look at the stack trace on what exception is being thrown. Then register an exception mapper with your ExceptionDTO as body.
For example, if UnrecognizedPropertyException is thrown then you can add:
#Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException> {
#Override
public Response toResponse(UnrecognizedPropertyException e) {
ExceptionDTO myDTO = // build response
return Response.status(BAD_REQUEST).entity(myDTO).build();
}
}
If you want to validate input parameters in the request, you should return status code 400 (Bad Request) along with the error details. You can simply send json
{ "error": { "message": "string received for parameter x, where as int expected" } with the response status code 400.
`
I did a bit of research and determined that the best way to encode a Java exception in JSON is to use a convention developed by Oasis that looks like this:
{
"error": {
"code": "400",
"message": "main error message here",
"target": "approx what the error came from",
"details": [
{
"code": "23-098a",
"message": "Disk drive has frozen up again. It needs to be replaced",
"target": "not sure what the target is"
}
],
"innererror": {
"trace": [ ... ],
"context": [ ... ]
}
}
}
details is a list that should have an entry for each nested cause exception in the chain.
innererror.trace should include the stack trace if you wish, as a list of string values.
The response status code should be 400 unless you have a good reason for making it something else, and the code in the structure should match whatever you sent.
Write one method to convert a Java exception to this format, and you are done. Use it consistently and your JS code will be able to handle and display the exception values.
More of the details of the other approaches evaluated and dismissed are covered in this blog post on JSON REST API – Exception Handling
https://agiletribe.purplehillsbooks.com/2015/09/16/json-rest-api-exception-handling/
Here is the java method to convert an exception to this format:
public static JSONObject convertToJSON(Exception e, String context) throws Exception {
JSONObject responseBody = new JSONObject();
JSONObject errorTag = new JSONObject();
responseBody.put("error", errorTag);
errorTag.put("code", 400);
errorTag.put("target", context);
JSONArray detailList = new JSONArray();
errorTag.put("details", detailList);
String lastMessage = "";
Throwable runner = e;
while (runner!=null) {
String className = runner.getClass().getName();
String msg = runner.toString();
runner = runner.getCause();
JSONObject detailObj = new JSONObject();
detailObj.put("message",msg);
int dotPos = className.lastIndexOf(".");
if (dotPos>0) {
className = className.substring(dotPos+1);
}
detailObj.put("code",className);
System.out.println(" ERR: "+msg);
detailList.put(detailObj);
}
JSONObject innerError = new JSONObject();
errorTag.put("innerError", innerError);
JSONArray stackList = new JSONArray();
runner = e;
while (runner != null) {
for (StackTraceElement ste : runner.getStackTrace()) {
String line = ste.getFileName() + ":" + ste.getMethodName() + ":" + ste.getLineNumber();
stackList.put(line);
}
stackList.put("----------------");
runner = runner.getCause();
}
errorTag.put("stack", stackList);
return responseBody;
}

Nested JSON Request with Volley -> Escaped chars

I want to make a post request with volley to a REST API.
Therefore, I create a JSONObject and put a JSON String generated from a class in it.
JSONObject jsonObject = new JSONObject();
String json = gson.toJson(MyClazz);
try {
jsonObject.put(PARAM, json);
}
catch (JSONException e1) {
e1.printStackTrace();
}
The problem is that the correct calculated JSON String gets escaped and can't be recognized on the back end.
So toJson() gives something like:
{
"device_identifier":"324234234",
"name":"NameMe",
"list":[
{"prop":"A","prop2":-10},
{"prop":"B","prop2":-12}
]
}
The jsonObject's output is like
{
"PARAM":{
\"device_identifier\":\"324234234\",
\"name\":\"NameMe\",
\"list\":[
{\"prop\":\"A\",\"prop2\":-10},
{\"prop\":\"B\","\prop2\":-12}
]
}
}
I need the PARAM for the JSON structure so I can't give it directly to the REST-API. Any ideas how I can avoid the additional escaping?
You could wrap your MyClazz object with a simple wrapper object, and then pass that wrapped object to Gson's toJson method.
Given this class based on your example JSON,
public class MyClazz {
public String device_identifier;
public String name;
public List<Prop> list;
public class Prop {
public String prop;
public Integer prop2;
}
}
here's a possible wrapper implementation. Note the use of com.google.gson.annotations.SerializedName which tells Gson to use the PARAM key in the JSON representation.
public class MyClazzWrapper {
public MyClazzWrapper(MyClazz myClazz) {
this.myClazz = myClazz;
}
#SerializedName("PARAM")
private MyClazz myClazz;
}
And here's an example using it:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
MyClazz myClazz = gson.fromJson("{\"device_identifier\":\"324234234\",\"name\":\"NameMe\",\"list\":[{\"prop\":\"A\",\"prop2\":-10},{\"prop\":\"B\",\"prop2\":-12}]}", MyClazz.class);
MyClazzWrapper wrapped = new MyClazzWrapper(myClazz);
System.out.println(gson.toJson(wrapped));
The above will print:
{
"PARAM": {
"device_identifier": "324234234",
"name": "NameMe",
"list": [
{
"prop": "A",
"prop2": -10
},
{
"prop": "B",
"prop2": -12
}
]
}
}

Categories