Custom JSON response with Spring MVC - java

Model
public class Organisation {
private String name;
public Organisation() { }
public Organisation(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
controller
#RequestMapping(method = RequestMethod.GET)
public List<Organisation> getAll() {
Organisation organisation = new Organisation("google");
List<Organisation> organisations = new ArrayList<>();
organisations.add(organisation);
return organisations;
}
This will give out response like this:
[
{
"name": "google"
}
]
What if we want something like this:
{
"data": [{
"type": "organisations"
"attributes": {
"name": "google"
}
]
}
So how to customize the json. I know that Spring MVC by default uses Jackson to convert models into JSON. Is there a way to customize it. I am trying to send response in JSONApi standard. Also can someone tell how to create links in responses

Create Classes as:
public class Object1 {
private List<Object2> data;
public Object1() {
}
public Object1(List<Object2> data) {
this.data = data;
}
//getters and setters
}
public class Object2 {
private String type;
private Object3 attributes;
public Object2() {
}
public Object2(String type, Object3 attributes) {
this.type = type;
this.attributes = attributes;
}
//getters and setters
}
public class Object3 {
private String name;
public Object3(String name) {
this.name = name;
}
public Object3() {
}
//getters and setters
}
Now your controller method shoul be like:
#RequestMapping(method = RequestMethod.GET)
public Object3 getAll() {
List<Object2> data = new ArrayList<>();
data.add(new Object2("organisations", new Object3("google")));
return new Object1(data);
}

Related

How to Get Json object and Json Array in Same KEY by retrofit for android

I am getting JSON Object when their is only one response(items) or JSON Array response but i want to array and object response.How to handle JSON Response?
JSON ARRAY when their is more than one items.And JSON OBJECT when their is only one items
.
{
"product":[
{
"items":[
{
"name":"foo",
"title":"toy"
},
{
"name":"foo",
"title":"toy"
}
]
},
{ "items":
{
"name":"foo",
"title":"toy"
}
}
]
}
First create model for this json Response using json to p
public class Example {
#SerializedName("product")
#Expose
private List<Product> product = null;
public List<Product> getProduct() {
return product;
}
public void setProduct(List<Product> product) {
this.product = product;
}
}
public class Item {
#SerializedName("name")
#Expose
private String name;
#SerializedName("title")
#Expose
private String title;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
public class Product {
#SerializedName("items")
#Expose
private List<Item> items = null;
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
Pass this Exmaple class into your response like
Call and get the data usning model

Json inside json not working in spring boot

I am trying to use JSON inside a JSON request.
for example:
{
"name":"newdeeeepaajlf",
"category":"fsafaa",
"jsonData":{
"a":"value"
}
}
now when I am trying to get it in my DTO which has
private JSONObject jsonData;
it gets converted in a blank JSON
{}
I am stuck in this.
We can use map to convert the data
public class TestModel {
private String name;
private String category;
private Map<String, Object> jsonObj;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Map<String, Object> getJsonObj() {
return jsonObj;
}
public void setJsonObj(Map<String, Object> jsonObj) {
this.jsonObj = jsonObj;
}
}
and use above class from controller like below
#PostMapping("/test")
public boolean test(#RequestBody TestModel model) {
System.out.println(model.getCategory());
System.out.println(model.getName());
JSONObject jsonObj = new JSONObject(model.getJsonObj());
System.out.println(jsonObj);
return true;
}
For request
{
"category":"json",
"name":"name",
"jsonObj": {
"a": "value"
}
}
it will print
json
name
{a=value}
you have a error in json if you have json something like below.
{
"name": "newdeeeepaajlf",
"category": "fsafaa",
"jsonData": {
"a": "value"
}
}
you can use this as a class
public class Codebeautify {
private String name;
private String category;
JsonData jsonDataObject;
// Getter Methods
public String getName() {
return name;
}
public String getCategory() {
return category;
}
public JsonData getJsonData() {
return jsonDataObject;
}
// Setter Methods
public void setName(String name) {
this.name = name;
}
public void setCategory(String category) {
this.category = category;
}
public void setJsonData(JsonData jsonDataObject) {
this.jsonDataObject = jsonDataObject;
}
}
public class JsonData {
private String a;
// Getter Methods
public String getA() {
return a;
}
// Setter Methods
public void setA(String a) {
this.a = a;
}
}
also json within json is working with in spring boot its a very common scenario. use ObjectMapper to map json with class.

Spring Boot - Hierarchical entities data is not returning from a rest API

I have an API method implemented in spring boot for Courses. It fetches the course by topic Id. The Course class is implemented as:
#Entity
public class Course {
#Id
private String id;
private String name;
private String description;
#ManyToOne
private Topic topic;
public Course() {
}
public Course(String id, String name, String description, String topicId) {
super();
this.id = id;
this.name = name;
this.description = description;
this.topic = new Topic(topicId, "", "");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void setTopic(Topic t) {
this.topic = t;
}
}
And the API method is implemented as:
#RequestMapping(method=RequestMethod.GET, value="/topics/{topicId}/courses")
public RestMessage getAllCourses(#PathVariable String topicId) {
try {
List<Course> course = courseService.getAllCourses(topicId);
message = new RestMessage(course,StatusCodeEnum.OK);
return message;
} catch (Exception e) {
message = new RestMessage(e.getMessage(),StatusCodeEnum.INTERNAL_SERVER_ERROR);
message.setException(e);
return message;
}
}
The method implementation is simple, it tries to get all the courses based on the topic id and return it as a RestMessage Object. I'm using postman for the testing and in the response I am getting the list of Course but the Topic entity data is discarded.
The api response is as:
{
"data": [
{
"id": "java-streams",
"name": "Java Streams",
"description": "Java Stream learning"
}
],
"httpStatus": "OK",
"statusCode": 200,
"exception": null
}
And the RestMessage Class is defined as:
public class RestMessage {
private Object data;
private StatusCodeEnum httpStatus;
private int statusCode;
private Exception ex;
public RestMessage() {
}
public RestMessage(Object d, StatusCodeEnum c) {
data = d;
httpStatus = c;
statusCode = c.val();
}
public void setData(Object d) {
data =d;
}
public void setHttpStatus(StatusCodeEnum c) {
httpStatus = c;
}
public void setStatusCode(int c) {
statusCode = c;
}
public void setException(Exception e) {
ex = e;
}
public void setStatusCode(StatusCodeEnum c) {
httpStatus = c;
}
public Object getData() {
return data;
}
public StatusCodeEnum getHttpStatus() {
return httpStatus;
}
public Exception getException() {
return ex;
}
public int getStatusCode() {
return statusCode;
}
}
However, I have tried to debug the API endpoint and before returning the RestMessage object I have data in the required shape but after getting the json response the Topic object is truncated for all the courses.
The debug data image is attached:
I wonder what I am doing wrong in this case?
The field topic from Course doesn't have a getter, that's why is ignored by JSON serializer.
You can use Lombok annotation to automatically generate getters and setters.
Just add #Dataon class definition and you will have generated getters and setters, constructor without parameters. You will have everything for what you can said that is POJO class.
Check this link: Project lombok

Convert a received JSON response to List<T> in Java

I am new to Java programming and I am working on a Spring Boot application with a REST service which will call another service and return a JSON response.
I am using OkHttpClient for handling this call.
However from the JSON response, I only require few attributes as final output in List format.
How can I extract only the required attributes from my okHttpCliwnt response ?
My response from the third party service looks like below :
{
"employeeDetail": [{
"employee": {
"name": "abc",
"age": "30",
"details": {
"role": "developer",
"phone": "123"
}
}
},
{
"employee": {
"name": "abc",
"age": "30",
"details": {
"role": "sr.developer",
"phone": "1234"
}
}
}
]
}
From this response, my final response needs to only be like below:
{
"employeeDetail": [{
"name": "abc",
"age": "30",
"role": "developer"
},
{
"name": "abc",
"age": "30",
"role": "sr.developer"
}
]
}
Please assist me.
I searched but for such nesting I couldn't find anything concrete. however I tried with JsonNode and I got to this.
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(str);
JsonNode empDetNode = rootNode.path("employeeDetail");
Iterator<JsonNode> elements = empDetNode.elements();
List<Employee> empList = new ArrayList<Employee>();
Gson gson = new Gson();
while (elements.hasNext()) {
Employee emp1 = new Employee();
JsonNode emp= elements.next();
JsonNode empl= emp.path("employee");
JsonNode name= empl.path("name");
JsonNode age= empl.path("age");
JsonNode details= empl.path("details");
JsonNode role= details.path("details");
emp1.setAge(age.toString());
emp1.setName(name.toString());
emp1.setRole(role.toString());
empList.add(emp1);
}
EmpDetl empdetl = new EmpDetl();
empdetl.setEmployeeDetl(empList);
Employee Class
public class Employee {
private String name;
private String age;
private String role;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
EmployeeDetl
import java.util.List;
public class EmpDetl {
private List<Employee> employeeDetl;
public List<Employee> getEmployeeDetl() {
return employeeDetl;
}
public void setEmployeeDetl(List<Employee> empLists) {
this.employeeDetl = empLists;
}
#Override
public String toString() {
return "EmpDetl [empLists=" + employeeDetl + "]";
}
}
I don't know how to convert JSON to List<> but you can convert JSON to Java object using Gson.
After that, you can add the contents of the object or the object itself to the list.
Here's a snippet from https://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
Gson gson = new Gson();
// 1. JSON to Java object, read it from a file.
Staff staff = gson.fromJson(new FileReader("D:\\file.json"), Staff.class);
// 2. JSON to Java object, read it from a Json String.
String jsonInString = "{'name' : 'mkyong'}";
Staff staff = gson.fromJson(jsonInString, Staff.class);
// JSON to JsonElement, convert to String later.
JsonElement json = gson.fromJson(new FileReader("D:\\file.json"),
JsonElement.class);
String result = gson.toJson(json);
Jackson might be the tool you are looking for. You just need to create a class, let's say Employee.java:
public class Employee {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private String age;
#JsonProperty("role")
private String role;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
and EmployeeDetail.java
import java.util.List;
#JsonRootName(value = "employeeDetail")
public class EmployeeDetail {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
More annotations, please refer
You have to do the parsing manually using org.json or some other json framework.

Same User dto but with different JsonProperty for two services

I am having two Spring Rest service create-employee and create-staff like as shown below
create-employee
#RequestMapping(value="/create-employee", method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<Void> createEmployee(final #RequestBody User user) {
try {
// employee createion logic
} catch (Exception exception) {
log.error("Exception in createEmployee:"+exception.getMessage());
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
create-staff
#RequestMapping(value="/create-staff", method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<Void> createStaff(final #RequestBody User user) {
try {
// staff creation logic
} catch (Exception exception) {
log.error("Exception in createStaff:"+exception.getMessage());
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
For both the services I am using a dto named User like as shown below:
public class User {
#JsonProperty("employeeName")
private String name;
#JsonProperty("age")
private Integer age;
#JsonProperty("managerName")
private String headName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getHeadName() {
return headName;
}
public void setHeadName(String headName) {
this.headName = headName;
}
}
Now the issue is that for both create-employee and create-staff since I am using User.java as the request body. The posting json body looks like this
{
"employeeName" : "string",
"age" : "integer",
"managerName" : "string"
}
but actually what I want is that for create-staff service I would like to have the json body as below
{
"staffName" : "string",
"age" : "integer",
"managerName" : "string"
}
and create-staff service I would like to have the json body as below
{
"employeeName" : "string",
"age" : "integer",
"managerName" : "string"
}
But for both the services I need to use the same User.java dto but with different JsonProperty for the two services
Can anyone please hep me on this
Jackson also supports JsonAlias which might be helpful for you, just make sure you updated your jacskon mapper to version 2.9.1
public class User {
#JsonAlias({"employeeName","staffName"})
private String name;
#JsonProperty("age")
private Integer age;
#JsonProperty("managerName")
private String headName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getHeadName() {
return headName;
}
public void setHeadName(String headName) {
this.headName = headName;
}
}

Categories