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

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"
}

Related

JsonSerializer: How to create a list in a json without involve elements in French braces?

I'm using JsonSerializer to format a Json in Java but I need a formatting in particular. I need formatting like this:
{
"atividades": {
"atividade": {
"numeroPA": "1350131018010243103A",
"numero": "1350131018010243103A001"
},
"atividade": {
"numeroPA": "1350131018010243103A",
"numero": "1350131018010243103A002"
}
}
}
However I am getting a json like this:
{
"atividades": [
{
"atividade": {
"numeroPa": "1350131018010243103A",
"numero": "1350131018010243103A001"
}
},
{
"atividade": {
"numeroPa": "1350131018010243103A",
"numero": "1350131018010243103A002"
}
}
]
}
This is a specific need of the project. I wonder if any of you have been through this and if you ever managed to solve it.
Below is the code that generates this json:
#XmlRootElement(name = "atividade")
#JsonRootName(value = "atividade")
#XmlAccessorType(XmlAccessType.FIELD)
#JsonPropertyOrder({"numeroPa", "numero"})
public class NormaAtividadeDTO implements INormaAtividadeERP {
private String numeroPa;
private String numero;
#JsonProperty("numeroPa")
public String getNumeroPa() {
return numeroPa;
}
public void setNumeroPa(String numeroPa) {
this.numeroPa = numeroPa;
}
#JsonProperty("numero")
public String getNumero() {
return numero;
}
public void setNumero(String numero) {
this.numero = numero;
}
}
public class NormaAtividadeSerializer extends JsonSerializer<List<NormaAtividadeDTO>> {
#Override
public void serialize(List<NormaAtividadeDTO> pLstNormaAtividade, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartArray();
for (NormaAtividadeDTO lNormaAtividadeDTO : pLstNormaAtividade) {
gen.writeStartObject();
gen.writeObjectField("atividade", lNormaAtividadeDTO);
gen.writeEndObject();
}
gen.writeEndArray();
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#JsonPropertyOrder({"atividades"})
public class NormaAtividadeTransacaoDTO implements INormaAtividadeTransacaoERP {
#XmlElement(name = "atividades")
#JsonDeserialize(contentAs = NormaAtividadeDTO.class)
#JsonSerialize(using = NormaAtividadeSerializer.class)
private List<NormaAtividadeDTO> lstNormaAtividadeDTO = new ArrayList<NormaAtividadeDTO>();
#JsonProperty("atividades")
public List<NormaAtividadeDTO> getLstNormaAtividadeDTO() {
return lstNormaAtividadeDTO;
}
public void setLstNormaAtividadeDTO(List<NormaAtividadeDTO> lstNormaAtividadeDTO) {
this.lstNormaAtividadeDTO = lstNormaAtividadeDTO;
}
}
json = objectMapper.writer().writeValueAsString(pObject);
Do you have any ideas?
Thank you in advance.

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 can I read a JSON with header and body with spring boot

Good morning I have a small query, I am doing a small web service rest with spring boot, the issue is that it is working fine and everything else, as I am doing as follows, receives a parameter and returns a response based on a Stored Procedue in the database:
But now I have changed the request, and it is including header and body, like the following:
{
"ValidateClient": {
"Header": {
"country": "VE",
"lang": "ES",
"entity": "TMVE",
"system": "76",
"subsystem": "APP",
"operation": "ValidateClient",
"timestamp": "2019-10-23T08:48:08.474Z",
"msgType": "REQUEST"
},
"Body": {
"validateClientRequest": {
"movil": "04141734272"
}
}
}
}
Which when executing it gives me an answer of not found the mobile, it is a default response when it cannot read the mobile parameter or it is sent empty
My Code
Main Class
package com.app.validate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ValidateClientApp {
public static void main(String[] args) {
SpringApplication.run(ValidateClientApp.class, args);
}
}
Controller
package com.app.validate.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.app.validate.dao.ValidateClientAppRepository;
import com.app.validate.entity.DriverBonificados;
import com.app.validate.entity.ResponseVo;
#RestController
public class ValidateClientAppController {
#Autowired
private ValidateClientAppRepository dao;
#PostMapping(value = "/ValidateClientApp",consumes = "application/json",produces="application/json")
public ResponseVo ValidateClient(#RequestBody DriverBonificados driver) {
//System.out.println(driver.getMovil());
return dao.validarClienteBonifiado(driver.getMovil());
}
}
Dao
package com.app.validate.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.app.validate.entity.DriverBonificados;
import com.app.validate.entity.ResponseVo;
#Repository
public interface ValidateClientAppRepository extends JpaRepository<DriverBonificados, Integer> {
#Query(nativeQuery = true,value = "call ValidacionClienteBonificado(:movil)")
ResponseVo validarClienteBonifiado(#Param("movil") String pMovil);
}
Entity
package com.app.validate.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="DriverBonificados")
public class DriverBonificados {
#Id
private int id;
private String movil;
private String contador;
private Date fecha_driver;
private Date fecha_alta;
private Date fecha_fin;
private Date codigo_transaccion;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMovil() {
return movil;
}
public void setMovil(String movil) {
this.movil = movil;
}
public String getContador() {
return contador;
}
public void setContador(String contador) {
this.contador = contador;
}
public Date getFecha_driver() {
return fecha_driver;
}
public void setFecha_driver(Date fecha_driver) {
this.fecha_driver = fecha_driver;
}
public Date getFecha_alta() {
return fecha_alta;
}
public void setFecha_alta(Date fecha_alta) {
this.fecha_alta = fecha_alta;
}
public Date getFecha_fin() {
return fecha_fin;
}
public void setFecha_fin(Date fecha_fin) {
this.fecha_fin = fecha_fin;
}
public Date getCodigo_transaccion() {
return codigo_transaccion;
}
public void setCodigo_transaccion(Date codigo_transaccion) {
this.codigo_transaccion = codigo_transaccion;
}
}
Interface Response Stored Procedue
package com.app.validate.entity;
public interface ResponseVo {
String getCode();
String getResult();
}
How could you do to read the Json with header and body? I'm new to spring boot
UPDATE
According to what Silverfang said, I created the classes said by him, but I get an error that I describe next:
BodyRequest.java
public class BodyRequest {
private String validateClientRequest;
private String movil;
public String getValidateClientRequest() {
return validateClientRequest;
}
public void setValidateClientRequest(String validateClientRequest) {
this.validateClientRequest = validateClientRequest;
}
public String getMovil() {
return movil;
}
public void setMovil(String movil) {
this.movil = movil;
}
}
HeaderRequest.java
package com.app.validate.controller;
import java.util.Date;
public class HeaderRequest {
private String country;
private String lang;
private String entity;
private String system;
private String subsystem;
private String operation;
private Date timestamp;
private String msgType;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public String getSubsystem() {
return subsystem;
}
public void setSubsystem(String subsystem) {
this.subsystem = subsystem;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
}
RequestBodyDemo.java
package com.app.validate.controller;
public class RequestBodyDemo {
private ValidateClientRequest ValidateClient;
public ValidateClientRequest getValidateClient() {
return ValidateClient;
}
public void setValidateClient(ValidateClientRequest validateClient) {
ValidateClient = validateClient;
}
}
ValidateClientRequest
package com.app.validate.controller;
public class ValidateClientRequest {
private BodyRequest Body;
private HeaderRequest Header;
public BodyRequest getBody() {
return Body;
}
public void setBody(BodyRequest body) {
Body = body;
}
public HeaderRequest getHeader() {
return Header;
}
public void setHeader(HeaderRequest header) {
Header = header;
}
}
My Controller (Update)
package com.app.validate.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.app.validate.dao.ValidateClientAppRepository;
import com.app.validate.entity.DriverBonificados;
import com.app.validate.entity.ResponseVo;
#RestController
public class ValidateClientAppController {
#Autowired
private ValidateClientAppRepository dao;
#PostMapping(value = "/ValidateClientApp",consumes = "application/json",produces="application/json")
public ResponseVo ValidateClient(#RequestBody RequestBodyDemo req) {
System.out.println(req.getValidateClient().getBody().getMovil());
return dao.validarClienteBonifiado(req.getValidateClient().getBody().getMovil());
}
}
The error I get:
From what I understand you have changed the request format and now want the same request body to work for the same controller.
I think you were trying to add the fields to the header. What you are doing here is not the right way to do it. It should goes to header section rather than in the body section of the Postman app. But doing so, you will have to specify these header separately as these are custom headers which will be a lot of work.
Answer to your question
Going by what you were trying to do. Since now you have changed the request body. You will have to make changes in the controller class too. Now it will require three classes If you want to do it in a modular way.
The first class will be BodyRequest.java
private string validateClientRequest;
private string movil;
The next class will be HeaderRequest.java
private string country;
private string lang;
private string entity;
private string system;
private string subsystem;
private string operation;
private Date timestamp;
private string msgType;
Next class will be ValidateClientRequest.java
private HeaderRequest Header;
private BodyRequest Body;
Now for the RequestBodyDemo class;
private ValidateClientRequest ValidateClient;
Note : Use appropriate Getter and setter along with #JsonProperty if you are masking the input request data.
Once these things are done. In your controller Instead of using Entity in #RequestBody Use the class RequestBodyDemo. Once that is done. Just try printing the values just to check whether you are getting them right or not. Then use getter for fetching any value that you need.
Edit :
public ResponseVo ValidateClient(#RequestBody RequestBodyDemo req) {
System.out.println(req.getValidateClient().getBodyrequest().getMovil());
return dao.validarClienteBonifiado(req.getValidateClient().getBodyrequest().getMovil());
}
Note : Use appropriate getter method here.

how to accept a List<List<String>> from json in rest web services

I have json input as
{"subkeys":[{"1","2", "3"},{"4","5","6"},{"7","8","9"}]
I need to get this as List < List < String > > or List < String[] >.
#PUT
#Path("/{key}/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public MyResponse loadData( List<List<String>> subkeys) {
}
I got the error like
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.util.List is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.util.List
at private java.util.List foobar.alkohol.register.webservice.jaxws.GetRelationsFromPersonResponse._return
The problem I can see here is due to the wrong format of the JSON input, the correct JSON in your case is:
{
"data" :[
{
"keys": ["123","456","789"],
"subkeys": [
["1", "2", "3"],
["1", "2", "3"],
["1", "2", "3"]
]
}
]
}
try with this and let know.
my code is as follows
#PUT #Path("/{key}/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public MyResponse loadData( MonitoringDataRequest monReq) {
}
#XmlRootElement(name="data")
public class MonitoringDataRequest {
private List<MonitoringData> data;
#XmlElement
public void setData(List<MonitoringData> data) {
this.data = data;
}
public List<MonitoringData> getData() {
return data;
}
}
#XmlRootElement(name="monitoring_data")
public class MonitoringData {
private List<String> keys;
private List<SubkeyData> subKeys;
#XmlElement
public void setKeys(List<String> keys) {
this.keys = keys;
}
public List<String> getKeys() {
return keys;
}
#XmlElement(name="subkeys")
public void setSubKeys(List<SubkeyData> subKeys) {
this.subKeys = subKeys;
}
public List<SubkeyData> getSubKeys() {
return subKeys;
}
}
#XmlRootElement(name="subkeys")
//#XmlAccessorType(XmlAccessType.NONE)
public class SubkeyData
{
private List<String[]> subkeys;
#XmlElement
public void setSubkeys(List<String[]> subkeys)
{
this.subkeys = subkeys;
}
public List<String[]> getSubkeys()
{
return subkeys;
}
}

type parameter in the response json: REST

I sent a request JSON through Postmaster and got a response in which includes
a field "type": "subPOJO", which isn't part of either my sub class or super class. How is it been placed in the response, if it is implicitly done then how to exclude it in the response. Thank you!
Response JSON:
{
"type": "subPOJO",
"superid": "XYZ",
"name": "Rest Response",
"number": 1212
}
The Response POJOs:
Super class:
package org.javaprojects.webapp.services;
public class SuperPOJO {
private String superid;
public String getSuperid() {
return superid;
}
public void setSuperid(String superid) {
this.superid = superid;
}
}
Sub Class:
package org.javaprojects.webapp.services;
public class SubPOJO extends SuperPOJO {
private String name;
private int number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
Check this out This may Help you