Using List for JSON Array - json

Updating based on further exploring and thanks to #pinaka30 for the comment-
I wanted to verify if I deserialize JSON array into List, will that preserve the sequence.
I took the below JSON
{
"MyJSON": {
"name": "Any Name",
"values": [
"1111",
"2222",
"3333",
"4444",
"5555",
"6666"
]
}
}
The DTO that I created is as follows:
package com.jsonrelated.jsonrelated;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"MyJSONMapping"
})
public class MyJSONMapping {
#JsonProperty("MyJSON")
#Valid
#NotNull
private MyJSON myJSON;
#JsonProperty("MyJSON")
public MyJSON getMyJSON() {
return myJSON;
}
#JsonProperty("MyJSON")
public void setMyJSON(MyJSON myJSON) {
this.myJSON = myJSON;
}
}
package com.jsonrelated.jsonrelated;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.util.List;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"name",
"values"
})
public class MyJSON {
#JsonProperty("name")
String name;
#JsonProperty("values")
List<String> values;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
}
Then I have created a REST API and sending that JSON as request Body
#RequestMapping(path="generateMyJSONChart",method=RequestMethod.POST,produces="application/json",consumes="application/json")
public String generateMyJSONChart(#Valid #RequestBody MyJSONMapping myJSONMapping, #RequestParam("type") #NotBlank String type) throws IOException {
List comparedProducts = myJSONMapping.getMyJSON().getValues();
Iterator i = comparedProducts.iterator();
while (i.hasNext())
{
String name = (String) i.next();
System.out.println(name);
}
return "nothing";
}
I was checking if the sequence of the values in "Values" as in
"values": [
"1111",
"2222",
"3333",
"4444",
"5555",
"6666"
]
are preserved if we deserialize them into List as in
#JsonProperty("values")
List<String> values;
I have run it multiple times with 100 elements in the values and I see the order is preserved.
Adding a good post already there Is the order of elements in a JSON list preserved? so mine seems to be duplicate.

Related

How to read dynamic objects that are appended with a number in GSON?

The result coming from an external API as..
BIBREF are dynamic, the we do not know how will be fetched
The index is appended to the name "BIBREF+number"
"bib_entries": {
"BIBREF0": {
"ref_id": <str>,
"title": <str>,
},
"BIBREF1": {
"ref_id": <str>,
"title": <str>,
},
...
...
"BIBREF25": {}
},
Defined a pojo as..
public class BibEntries {
private BibRef bibRef;
# ...getters/setters
public class BibRef {
private String ref_id;
private String title;
# ...getters/setters
}
}
Defined the class as:
JsonObject bibEntriesObject = jsonObject.get("bib_entries").getAsJsonObject();
BibEntries bibEntries = new Gson().fromJson(bibEntriesObject, BibEntries.class);
Learning GSON and using GenericTypes seemed confusing. How can i update the above code to read the dynamic objects (using gson 2.8.6)?
With some help from my colleague, here's the solution
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class Test {
private static final Gson gson = new
GsonBuilder().serializeNulls().setPrettyPrinting().create();
public static void main(String[] args) {
// Original Json Input
String jsonRequest = "{ \"bib_entries\": { \"BIBREF0\": { \"ref_id\": \"One\", \"title\": \"two\"},"
+ "\"BIBREF1\": { \"ref_id\": \"three\", \"title\": \"four\"} } }";
//Convert string to JsonObject
JsonObject convertedObject = new Gson().fromJson(jsonRequest, JsonObject.class);
JsonObject object = convertedObject.get("bib_entries").getAsJsonObject();
//Init Class
BibEntries bibEntries = new BibEntries();
List<BibEntries.Bibref> list = new ArrayList<>();
//Mapping the object to class
object.keySet().stream().forEach((key) -> {
// We can add more here..
BibEntries.Bibref bibref = gson.fromJson(object.get(key), BibEntries.Bibref.class);
list.add(bibref);
bibEntries.setListBibref(list);
});
//Original
System.out.println(convertedObject);
// Print the final result
System.out.println(gson.toJson(bibEntries));
}
public static class BibEntries {
List<Bibref> listBibref;
public static class Bibref {
#SerializedName("ref_id")
private String refId;
#SerializedName("title")
private String title;
public String getRefId() {
return refId;
}
public void setRefId(final String refId) {
this.refId = refId;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}
public List<Bibref> getListBibref() {
return listBibref;
}
public void setListBibref(final List<Bibref> listBibref) {
this.listBibref = listBibref;
}
}
}

how to parse below Json file in java , which has no key [duplicate]

This question already has answers here:
How to read json file into java with simple JSON library
(21 answers)
Closed 3 years ago.
{
"type": "telemetry",
"timestamp": 1234,
"device": 5678,
"value": {
[
{"battery_level": 87},
{"var2": 2},
{"var3": 3}
]
}
}
I want to pasre this json file in java code using jsonobject and jsonarray Here, I'm stuck up at values keyword inside has no key to array.
Your valid JSON would be -
{
"type": "telemetry",
"timestamp": 1234,
"device": 5678,
"value":
[
{"battery_level": 87},
{"var2": 2},
{"var3": 3}
]
}
You can then use following JAVA POJO objects to parse your json into the java object -
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"type",
"timestamp",
"device",
"value"
})
public class Example {
#JsonProperty("type")
private String type;
#JsonProperty("timestamp")
private Integer timestamp;
#JsonProperty("device")
private Integer device;
#JsonProperty("value")
private List<Value> value = null;
#JsonProperty("type")
public String getType() {
return type;
}
#JsonProperty("type")
public void setType(String type) {
this.type = type;
}
#JsonProperty("timestamp")
public Integer getTimestamp() {
return timestamp;
}
#JsonProperty("timestamp")
public void setTimestamp(Integer timestamp) {
this.timestamp = timestamp;
}
#JsonProperty("device")
public Integer getDevice() {
return device;
}
#JsonProperty("device")
public void setDevice(Integer device) {
this.device = device;
}
#JsonProperty("value")
public List<Value> getValue() {
return value;
}
#JsonProperty("value")
public void setValue(List<Value> value) {
this.value = value;
}
}
-----------------------------------com.example.Value.java-----------------------------------
package com.example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"battery_level",
"var2",
"var3"
})
public class Value {
#JsonProperty("battery_level")
private Integer batteryLevel;
#JsonProperty("var2")
private Integer var2;
#JsonProperty("var3")
private Integer var3;
#JsonProperty("battery_level")
public Integer getBatteryLevel() {
return batteryLevel;
}
#JsonProperty("battery_level")
public void setBatteryLevel(Integer batteryLevel) {
this.batteryLevel = batteryLevel;
}
#JsonProperty("var2")
public Integer getVar2() {
return var2;
}
#JsonProperty("var2")
public void setVar2(Integer var2) {
this.var2 = var2;
}
#JsonProperty("var3")
public Integer getVar3() {
return var3;
}
#JsonProperty("var3")
public void setVar3(Integer var3) {
this.var3 = var3;
}
}
After your Java objects and JSON is in place use jackson to do the mapping -
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "{'name' : 'mkyong'}";
//JSON from file to Object
User user = mapper.readValue(new File("c:\\user.json"), Example.class);

Data mismatch between Json response and database

I'm retrieving data from mysql using spring boot, hibernate and producing the response as REST service. But while checking in Postman the data mismatches. Here is my code.
Controller Class:
#RestController
public class NotificationController<T> extends RestUtils<T> {
#Autowired
NotificationService<T> service;
#RequestMapping(value = "/notification/getNotifications", method = RequestMethod.POST, headers = "Accept=application/json")
public #ResponseBody Object getNotifications(#RequestBody NotificationBean notificationBean) {
try {
return getSuccessResponse(service.getNotifications(notificationBean), "Total Count: ",
service.getNotificationsCount(notificationBean));
} catch (StudawnException e) {
return getErrorResponse(e.getMessage());
}
}
}
Service Implementation:
#Service
public class NotificationServiceImpl<T> implements NotificationService<T> {
#Autowired
NotificationRepository notificationRepository;
#SuppressWarnings("deprecation")
#Transactional
#Override
public Object getNotifications(NotificationBean notificationBean) throws StudawnException {
Sort sort = new Sort(new Sort.Order(Direction.DESC, "dateCreated"));
Pageable pageable = new PageRequest(notificationBean.getPage(), notificationBean.getSize(), sort);
return notificationRepository.findNotificationsByStudentId(notificationBean.getStudentId(), pageable);
}
}
Repository:
#Repository
public interface NotificationRepository<T> extends JpaRepository<Notification, Integer> {
#Query(NotificationQuery.findNotificationsByStudentId)
List<Notification> findNotificationsByStudentId(#Param("studentId") Integer studentId, Pageable pageable);
#Query(NotificationQuery.findNotificationsCountByStudentId)
Integer findNotificationsCountByStudentId(#Param("studentId")Integer studentId);
}
Query class:
public class NotificationQuery {
public static final String findNotificationsByStudentId = "select n from #{#entityName} n where n.student.studentId = :studentId and n.isActive=true";
public static final String findNotificationsCountByStudentId = "select count(n) from #{#entityName} n where n.student.studentId=:studentId and n.isActive=true";
}
Model class
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "notification")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = { "dateCreated" }, allowGetters = true)
public class Notification {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "notification_id")
private int notificationId;
#ManyToOne
#JoinColumn(name = "student_id")
private Student student;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_date", nullable = false, updatable = false)
#CreatedDate
private Date dateCreated;
#Column(name = "is_active")
private boolean isActive;
#Column(name = "has_read")
private boolean hasRead;
#Column(name = "message", length = 150)
private String message;
public int getNotificationId() {
return notificationId;
}
public void setNotificationId(int notificationId) {
this.notificationId = notificationId;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public boolean isHasRead() {
return hasRead;
}
public void setHasRead(boolean hasRead) {
this.hasRead = hasRead;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Json Request
{
"studentId":101,
"page":0,
"size":10
}
Json Response
The date in 'dateCreated' field mismatch with database. The actual date in DB is '2018-03-06' but in response it is '2018-03-05'
{
"response": [
{
"notificationId": 4,
"student": {
"studentId": 101,
"studawnId": "1234",
"firstName": "arun",
"lastName": "kumar",
"emailId": "arun#xyz.com",
"mobileNumber": "987654",
"dateOfBirth": "1990-03-02T18:30:00.000+0000",
"gender": "male",
"profilePicture": "Pictures",
"hasTermsAccepted": true,
"dateCreated": "2018-03-02T18:30:00.000+0000",
"dateModified": "2018-03-02T18:30:00.000+0000",
"aadhaarNumber": "565497",
"addressOne": "adyar",
"addressTwo": "chennai",
"pincode": "600096",
"tickets": [],
"active": true,
"firstTimeLogin": true,
"school": true,
"college": true
},
"dateCreated": "2018-03-05T18:30:00.000+0000",
"hasRead": true,
"message": "User 1 has sent a msg to you",
"active": true
}
]
}
Thanks in advance.
I think you should check timezones. It looks like you have saved the date in your local timezone, but when you retrieve it from database and send to client you use GMT timezone.

How to get rest response that contains only certain object's json?

My goal is to get rest services working on spring boot web application.
But I am struggling with finding out how to tell response to include object's json only.
To be more precise, when calling http://localhost:8080/api/db/Keyboard/2, I intend to receive object with id 2 in json format and only:
{
"id": 2,
"language": "en"
}
But instead I get:
{
"status": 200,
"entity": {
"id": 2,
"language": "en"
},
"metadata": {},
"length": -1,
"allowedMethods": [],
"cookies": {},
"headers": {},
"actualEntity": {
"id": 2,
"language": "en"
},
"links": [],
"statusInfo": {
"reasonPhrase": "OK",
"statusCode": 200,
"family": "SUCCESSFUL"
},
"stringHeaders": {}
}
Clearly response contains too much info. Only the entity part is needed. How to reach intended result / adjust conditionally the response?
Below some files that might be relevant.
TestController.java:
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import main.domain.DaoApi;
import main.domain.Keyboard;
#RestController
public class TestController<T, K> {
private final static Map<String, Class<?>> tableClassMap = new HashMap<>();
#Autowired
private DaoApi<T, K> daoApi;
static {
addEntryTableClassMap(Keyboard.class);
}
#RequestMapping(value = "/api/db/{tableName}/{id}", method = RequestMethod.GET)
public Response getById(#PathVariable(value = "tableName") String tableName, #PathVariable(value = "id") Integer id) {
ResponseBuilder responseBuilder;
T entity = (T) daoApi.findById((Class<T>) getClassFromTableClassMap(tableName), id);
if (entity != null) {
responseBuilder = Response.ok(entity);
} else {
responseBuilder = Response.status(Status.NOT_FOUND);
}
return responseBuilder.build();
}
private static <C> void addEntryTableClassMap(Class<C> clazz) {
tableClassMap.put(clazz.getSimpleName().toLowerCase(), clazz);
}
private static <C> Class<C> getClassFromTableClassMap(String tableName) {
return (Class<C>) tableClassMap.get(tableName.toLowerCase());
}
}
Keyboard.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.transaction.annotation.Transactional;
#Transactional
#Entity
#Table(name = "keyboard")
public class Keyboard {
#Id
#Column(updatable = false)
private int id;
private String language;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
DaoApi.java:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class DaoApi<T, K> {
#Autowired
SessionFactory sessionFactory;
public T findById(Class<T> clazz, Integer id) {
Session session = sessionFactory.openSession();
T t = (T) session.get(clazz, id);
session.close();
return t;
}
}
Received comment that helped me to solution:
#RequestMapping(value = "/api/db/{tableName}/{id}", method = RequestMethod.GET)
public T getById(#PathVariable(value = "tableName") String tableName, #PathVariable(value = "id") Integer id) {
ResponseBuilder responseBuilder;
T entity = (T) daoApi.findById((Class<T>) getClassFromTableClassMap(tableName), id);
if (entity != null) {
responseBuilder = Response.ok(entity);
return (T) responseBuilder.build().getEntity();
} else {
responseBuilder = Response.status(Status.NOT_FOUND);
//some additional code here
return (T) responseBuilder.build();
}
}

How to parse JSON using GSON without implementing custom serializer and deserializer?

Sample JSON :
{
"outputs": [
{
"ports": {
"1521/tcp/oracle_tnslsnr": [
{
"hostname": "172.27.64.253"
}
]
},
"has_attachment": 0,
"custom_description": null,
"plugin_output": "Nothing here",
"hosts": null,
"severity": 3
}
]
}
I have parsed the same using Jackson but want to do it with GSON.
this is one the weirdest response i have written convenience model classes to reproduce the response I hope this helps
OutOfNamesMate
import com.google.gson.annotations.SerializedName;
public class OutOfNamesMate {
#SerializedName("hostname")
private String hostname;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
}
Port
import java.util.ArrayList;
import com.google.gson.annotations.SerializedName;
public class Port {
#SerializedName("1521/tcp/oracle_tnslsnr")
private ArrayList<OutOfNamesMate> outOfNamesMates;
public ArrayList<OutOfNamesMate> getOutOfNamesMates() {
return outOfNamesMates;
}
public void setOutOfNamesMates(ArrayList<OutOfNamesMate> outOfNamesMates) {
this.outOfNamesMates = outOfNamesMates;
}
}
Output.java
import com.google.gson.annotations.SerializedName;
public class Output {
#SerializedName("ports")
private Port ports;
#SerializedName("has_attachment")
private String has_attachment;
#SerializedName("custom_description")
private String custom_description;
#SerializedName("plugin_output")
private String plugin_output;
#SerializedName("hosts")
private String hosts;
#SerializedName("severity")
private String severity;
public Port getPorts() {
return ports;
}
public void setPorts(Port ports) {
this.ports = ports;
}
public String getHas_attachment() {
return has_attachment;
}
public void setHas_attachment(String has_attachment) {
this.has_attachment = has_attachment;
}
public String getCustom_description() {
return custom_description;
}
public void setCustom_description(String custom_description) {
this.custom_description = custom_description;
}
public String getPlugin_output() {
return plugin_output;
}
public void setPlugin_output(String plugin_output) {
this.plugin_output = plugin_output;
}
public String getHosts() {
return hosts;
}
public void setHosts(String hosts) {
this.hosts = hosts;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
}
Response
import java.util.ArrayList;
import com.google.gson.annotations.SerializedName;
public class Response {
#SerializedName("outputs")
private ArrayList<Output> output;
public ArrayList<Output> getOutput() {
return output;
}
public void setOutput(ArrayList<Output> output) {
this.output = output;
}
}
Test Code
following is the test code to check if the classes are working,
you can use above model classes in your code but following code is strictly made to match your data by no means that is a standard way of generating JSON data, it is up to you how do you want to populate your object
import java.util.ArrayList;
import com.google.gson.Gson;
public class TestDrive {
public static void main(String[] args) {
OutOfNamesMate mate = new OutOfNamesMate();
mate.setHostname("172.27.64.253");
ArrayList<OutOfNamesMate> mates = new ArrayList<>();
mates.add(mate);
Port port = new Port();
port.setOutOfNamesMates(mates);
Output output = new Output();
output.setPorts(port);
output.setHas_attachment("0");
output.setCustom_description("");
output.setPlugin_output("Nothing here");
output.setHosts("");
output.setSeverity("3");
String result = (new Gson()).toJson(output);
System.out.println(""+result);
}
}
Output
{
"ports": {
"1521/tcp/oracle_tnslsnr": [
{
"hostname": "172.27.64.253"
}
]
},
"has_attachment": "0",
"custom_description": "",
"plugin_output": "Nothing here",
"hosts": "",
"severity": "3"
}