How do you deserialize JSON in java, using JSON.org - java

I am using "org.json" for JSON. I am able to serialize any class into a JSON string, using JSONObject. However, I'm not sure how to go the other way. How does one Deserialize a JSON string back into a class instance?
This code works to serialize it. I use JSONObject, and I provide a list of field names as a second argument to the constructor - User.JSONFieldMap().
int randomValue = rnd.nextInt(10000);
String userName = "JavaUnitTest_" + randomValue;
User newUser = new User();
newUser.UserName = userName;
newUser.DisplayName = "Java Unit Test";
newUser.EmailAddress = userName + "#SomeDomainName.com";
JSONObject jsonUser = new JSONObject(newUser, User.JSONFieldMap());
String userStringified = jsonUser.toString();
I'm not sure how, or if it is possible to be able to do something like this:
User myUser = MagicJSONDeserializer.DeserializeIt("{ some JSON string}");
Thanks for any help, I come from a .net/C#/Microsoft background, so Java is very new to me.

That library does not provide such functionality directly. You can use any of hundreds of other Java JSON libraries that do, such as Gson, Jackson, or flexjson.
The indirect way of doing it would be to retrieve each value from the JSON and perform custom deserialization on that value before assigning it to an object field.

Update for someone interested in other solution. It can be achieved using com.fasterxml.jackson.databind as follows:
import com.fasterxml.jackson.databind.ObjectMapper;
String userStr = "{ \"NAME\" : \"John\" }";
User user = new ObjectMapper().readValue(userStr, User.class);
It uses ObjectMapper to convert byte[] or in this caseString to java object. This solution needs to have class User correctly annotated for example with #JsonProperty annotations. Otherwise it won't be able to match json key-values with class attributes.
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
public class User {
#JsonProperty("NAME")
String name;
#JsonGetter("NAME")
public String getName() {
return name;
}
#JsonSetter("NAME")
public void setName(String name) {
this.name = name;
}
}

Related

How can I introduce escape characters to my JSON mapper?

I am trying to make a simple thing using com.fasterxml.jackson.databind.ObjectMapper.
I have an object I want to translate to String.
class Car{
String color;
String brand;
//... more class info
}
It is working fine and I get my String as it should but the result looks like this:
{"color: "blue", "brand": "toyota" }
Is it possible to make it look like:
{\"color\": \"blue\", \"brand\", \"toyota\" }
I'm not sure if this breaks the JSON expected format.
I've read the docs and seems like I can use this:
ObjectMapper().factory.setCharacterEscapes(...)
But I'm not sure how to pass it or from which repo. Any ideas?
Use Jackson to generate valid JSON payload and StringEscapeUtils to escape it.
Example code:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.text.StringEscapeUtils;
public class EscapeJsonApp {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(new Car("blue", "Toyota"));
String escapedJson = StringEscapeUtils.escapeJson(json);
System.out.println(escapedJson);
}
}
class Car {
String color;
String brand;
// getters, setters, constructor
}
Above code prints:
{\"color\":\"blue\",\"brand\":\"Toyota\"}
Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
I am basically trying to make a mapper for an sort of inner object to
match a SNS format https://docs.aws.amazon.com/sns/latest/dg/sns-send-custom-platform-specific-payloads-mobile-devices.html
Here's one of the examples from that page:
{
"GCM":"{\"data\":{\"message\":\"Check out these awesome deals!\",\"url\":\"www.amazon.com\"}}"
}
That's a JSON object with a single field named "GCM" whose value is a string. The content of the string is another JSON object.
Let's take your Car class as an example, and assume you want to generate this JSON as your output:
{
"car": "{\"color\": \"blue\", \"brand\": \"toyota\"}"
}
First you'll need to convert your Car object to a JSON string. Then you create another JSON object and stuff the car's JSON string into a field of this outer object:
String carJson = objectMapper.writeValueAsString(myCar);
Map<String, Object> outerObject = singletonMap("car", carJson);
String finalResult = objectMapper.writeValueAsString(outerObject);
I think that you can use something like JSONObject.quote(json):
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(new Car("blue", "Toyota"));
System.out.println(JSONObject.quote(json));
Output:
"{\"color\": \"blue\", \"brand\", \"toyota\" }"

Convert multiple Java Beans to JSON

I have multiple Java bean classes that are associated to each other (JSON Array + JSON Object) since they have a nested structure.
There are about 10 classes. Is there a way to collectively convert these classes or at-least one by one?
I had created these classes out of a JSON data which I don't have access to right now.
So, now, what I'm looking forward is to create a dummy JSON out of those classes.
Using GSON, I tried converting one of these Bean classes however, I got an empty result. Here is one of the beans called Attachment.java.
Attachment.java
package mypackagename;
import java.io.Serializable;
public class Attachment implements Serializable{
private Payload payload;
private String type;
public Payload getPayload() {
return payload;
}
public void setPayload(Payload payload) {
this.payload = payload;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Implementation
Gson gson = new Gson();
Attachment attachment = new Attachment();
String json = gson.toJson(attachment);
Sure you got an empty result. Because your JSON object is empty. You should add data to your object and test it again as below:
Attachment attachment = new Attachment(new Payload("Test Payload"), "Test attachment");
String json = new Gson().toJson(attachment);
Log.e("Test", "Json: " + json); // result: Json: {"payload":{"test":"Test Payload"},"type":"Test attachment"}
To avoid empty object, you have to set a default value to your payload and type becaus Gson will ignore any null value.
This section of the Gson User Guide: https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects
The fourth bullet point explains how null fields are handled.

Converting a RequestBody json to an Object - Spring Boot

I am a begineer in java development but has previous experience on programming languages like PHP and Python. So little confused on how to proceed on spring boot with the development.
I am developing a rest API which has the following request
{
"key":"value",
"key1":"value1",
"platform_settings":[
{"key":"value"}
]
}
What I did
I created a RestController which accepts the http request and created a function for the resource
public Share share(#RequestBody final Share share) {
LOGGER.debug("This is the request", share);
return share; //
}
Question 1 : If it was any other programming language like PHP or Python, there will be helper function which will accept the json request and convert it to object which I can easily work on.
In python it is as simple as
import json
import requests
response = requests.get(...)
json_data = json.loads(response.text)
//can work on json_data anyway I want.
But in java, I will have to create a POJO class, or have jackson/JPA entity as dependency which will map the request to a Class (Which I should predefine with the requests).
Is there any better way I can do this? For every request I make, I will have to create a Class which the request can be mapped to and I will have to define the class
Entity
package com.payunow.socialsharemodule.models;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Share {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String key;
private String key1;
private Map<String,String> platform_settings;
public Share(String name, String description,Map<String,String> platform_settings) {
this.key = key;
this.key1 = key1;
this.platform_settings = platform_settings;
}
//for JPA
public Share() {}
public String getKey() {
return key;
}
public String getKey1() {
return key1;
}
public Map<String,String> getPlatform_settings() {
return platform_settings;
}
}
For every request I make, I will have to create a class defining all its variables inside. Is this the only way to do this?
You need to have Jackson dependecy for coversion of json to java object. But spring provides it by default, so you don't have to add it explicitly.
You don't need a JPA Entity. This is needed only when you want to store the recieved data into database.
Just to recieve the request you don't have to create a separate pojo class. Look at this code
#PostMapping("/json")
public JSONObject getGeneric(#RequestBody String stringToParse){
JSONParser parser = new JSONParser();
JSONObject json = null;
try {
json = (JSONObject) parser.parse(stringToParse);
} catch (ParseException e) {
e.printStackTrace();
}
return json;
}
As you can see here it takes a string as a request and converts it into a generic JSONObject. So basically you can pass any json to this endpoint.
You CanUse ObjectMapper class it has methods like convertValue and realValue..

Parse Json with com.fasterxml.jackson instead of org.json

I was wondering if it is possible to do this exact operation but with the jackson library.
String repo = response.toString();
JSONObject json = new JSONObject (repo);
String nameOfUser = json.getJSONObject(facebookID).getString("name");
Thank you,
Yes. Something like:
ObjectMapper mapper = new ObjectMapper(); // reuse, usually static final
JsonNode ob = mapper.readTree(response.toString()); // or from File, URL, InputStream, Reader
String nameOfUser = ob.path(facebookID).path("name").asText();
// note: '.get()' also works, but returns nulls, 'path()' safer
although even more convenient access is often done using JSON Pointer expressions, like:
String name = ob.at("/person/id").asText();
but I assume facebookID is an id from some other source.
UPDATE: as per comment below, structure you want may actually be POJO like:
public class Response {
public User facebookID;
}
public class User {
public String id;
public String email;
public String first_name;
// ... and so forth: fields and/or getter+setter
}
and then you can bind directly into class like so:
Response resp = mapper.readValue(response.toString(), Response.class);
String name = resp.facebookID.name;
So there's more than one way to do it with Jackson.

Parsing JSON object using jQuery and GSON returned by Spring controller

I was looking for some solution around here and I didnt find any correct answer to my question so I would like to ask you.
I have POJO with some simple attribs. and one List of another POJOs.
public class Standard implements Serializable {
private String id;
private String title;
private String description;
private Set<Interpretation> interpretations = new LinkedHashSet<Interpretation>();
}
public class Interpretation implements Serializable {
private String id;
private String title;
private String description;
}
In my controller class, I am returning Standard POJO with GSON.
#RequestMapping(value="/fillStandard", method= RequestMethod.GET)
public #ResponseBody String getStandard(#RequestParam String id) {
Standard s = DAOFactory.getInstance().getStandardDAO().findById(id);
return new Gson().toJson(s);
}
The question is, am I able to get the list of interpretations in my Standard POJO using jQuery ? Something like :
function newStandard() {
$.get("standard/fillStandard.htm", {id:"fe86742b2024"}, function(data) {
alert(data.interpretations[0].title);
});
}
Thanks a lot !
EDIT:
Well, thanks to #Atticus, there is solution of my problem. Hope that it will help somebody.
#RequestMapping(value="/fillStandard", method= RequestMethod.GET, produces="application/json")
public #ResponseBody Standard getStandard(#RequestParam String id) {
Standard s = DAOFactory.getInstance().getStandardDAO().findById(id);
return s;
}
Using #ResponseBody allows you to return the whole POJO, but you need to add produces="application/json" to your #RequestMapping annotation. Then you will be able to catch a returning object as JSON in jQuery like as I supposed.
function newStandard() {
$.get("standard/fillStandard.htm", {id:"idOfStandard"}, function(data) {
alert(data.id); //Standard id
alert(data.interpretations[0].title); //id of Interpretation on first place in array
});
Well you have to create and register your custom serializer.
It goes like this:
//You create your builder that registers your custom serializer with the class you want to serialize
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Standard.class, new StandardSerializer());
//Then you create your Gson object
Gson gson = builder.create();
//Then you pass your object to the gson like
Standard s = DAOFactory.getInstance().getStandardDAO().findById(id);
gson.toJson(s);
Your serializer looks like this:
public class StandardSerializer implements JsonSerializer<Standard>{
#Override
public JsonElement serialize(Standard src, Type typeOfSrc,
JsonSerializationContext context) {
JsonObject obj = new JsonObject();
//You put your simple objects in like this
obj.add("id",new JsonPrimitive(src.getId()));
//You put your complex objects in like this
JsonObject interpretations = new JsonObject();
//Here you need to parse your LinkedHashSet object and set up the values.
//For the sake of simplicity I just access the properties (even though I know this would not compile)
interpretations.add("title", src.getInterpretation().getTitle());
obj.add("interpretations", interpretations);
return obj;
}
}
In this case your Json would look something like:
{"id":"idValue", "title":"titleValue", "description":"descriptionValue", "interpretations":["id":"interpretationIdValue"]}
Now, you can access your data with jQuery like this:
function newStandard() {
$.get("standard/fillStandard.htm", {id:"fe86742b2024"}, function(data) {
alert(data.interpretations.title);
});
}
I hope this helps.
EDIT:
I see that your response gets converted to the declared method argument type which is String (as stated here: 16.3.3.2 Supported method return types). But what you really want is your Standrad POJO converted to JSON. I am not very familiar with Spring but as I have read here (16.3.2.6 Producible Media Types) there is another, maybe easier solution. If you want to return a JSON object, then change the return type of the
getStandard method to Standard instead of String and add produces="application/json" to your #RequestMapping annotation. As far as I have read this should tell Spring that the return type should be converted to JSON. In this case you do not need to use Gson.

Categories

Resources