How to get a string without "" in json response - json

I am new to springboot, i am getting a response as below in my json response:
"Number": "08002050"
I have defined it as String in my spring boot app.
I want to get a response as below:
"Number": 08002050
How do i accomplish this. please help

You can manage it in server side with a tricky way.
public class User {
private int id;
private String name;
#JsonIgnore // ignore this field when serialize
private String number;
#JsonProperty(value = "number") // change name of field when serialize
private int intValueOfNumber;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getIntValueOfNumber() {
return Integer.parseInt(number); // parse number string to int
}
public void setIntValueOfNumber(int intValueOfNumber) {
this.intValueOfNumber = intValueOfNumber;
}
}
In this entity #JsonIgnore annotation is ignore your field for JSON serialization and pass intValueOfNumber as int to JSON. Your json will be following:
{"id":1,"name":"Java","number":44124}
You may lost zero suffix of number string when you parse it to int.

Related

How to assign json kafka message to Java object?

I created a kafka consumer service using spring boot. I need to get the message from the kafka and assign it to the java object and do some calculations according to the data in the object and store it in MongoDB database.
Here is my kafka listner.
#KafkaListener(topics = "neworder", groupId = "group_json",
containerFactory = "orderKafkaListenerFactory")
public void consumeJson(List<Order> order) {
System.out.println("Consumed JSON Message: " + order);
}
Here is the received kafka message.
Consumed JSON Message: [{Id=11, FualType=Petrol 92, Capacity=33000}]
Here is my Java class.
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document("Order")
public class Order {
#Id
private int id;
private String type;
private int capacity;
public Order() {
}
public Order(int id, String type, int capacity) {
this.id = id;
this.type = type;
this.capacity = capacity;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
}
I need to assign the received message data from kafka to this java class.
Anyone can help me?
I assume you are getting some errors at the moment. It would help if you could add them to your question.
First, since the fields in the json of the Kafka message do not match those of your java class, you have to annotate them:
#Id
#JsonProperty("Id")
private int id;
#JsonProperty("FualType")
private String type;
#JsonProperty("Capacity")
private int capacity;
In terms of configuration of the consumer, normally it is enough to configure the JsonDeserializer for the value of the kafka message and use it in the ConsumerFactory:
#Bean
public ConsumerFactory<String, List<Order>> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}
and
#Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
...
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class);
props.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS, JsonDeserializer.class.getName());
...
return props;
}

SpringBoot JSON not deserializing into my request model

I am using SpringBoot and trying to deserialize JSON like:
{
"userId": "Dave",
"queryResults": {
"id": "ABC",
"carData": {.....},
"carId": "Honda",
"status": 0,
"model": "X"
}
}
, into MyRequestModel clas:
public class MyRequestModel {
private String userId;
private String: queryResults;
}
, that is received as #RequestBody parameter in my #PostMapping method that looks like:
#PostMapping
public String postDate(#RequestBody MyRequestModel data) {
...
return "posted";
}
The above queryResults field is supposed to be stored as a CLOB in a database.
Problem I am having is that if I send this JSON to hit my endpoint (PostMapping) method, it cannot deserialize it into MyRequestModel and I get this error:
Cannot deserialize instance of java.lang.String out of START_OBJECT token
at [Source: (PushbackInputStream); line: 3, column: 18] (through reference chain: MyRequestModel["queryResults"])]
I guess the real answer to your question is: if you NEED the queryResults property to be a String, then implement a custom deserializer.
If not, then, use one of the alternatives that Jonatan and Montaser proposed in the other answers.
Implementing a custom deserializer within Spring Boot is fairly straightforward, since Jackson is its default serializer / deserializer and it provides a easy way to write our own deserializer.
First, create a class that implements the StdDeserializer<T>:
MyRequestModelDeserializer.java
public class MyRequestModelDeserializer extends StdDeserializer<MyRequestModel> {
public MyRequestModelDeserializer() {
this(null);
}
public MyRequestModelDeserializer(Class<?> vc) {
super(vc);
}
#Override
public MyRequestModel deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String userId = node.get("userId").asText();
String queryResults = node.get("queryResults").toString();
MyRequestModel model = new MyRequestModel();
model.setQueryResults(queryResults);
model.setUserId(userId);
return model;
}
}
Second, mark your class to be deserialized using your custom deserializer by using the #JsonDeserialize annotation:
MyRequestModel.java
#JsonDeserialize(using = MyRequestModelDeserializer.class)
public class MyRequestModel {
private String userId;
private String queryResults;
}
It's done.
queryResults is a String on Java side but it is an Object on JSON side.
You will be able to deserialize it if you send it in as a String:
{
"userId": "Dave",
"queryResults": "foo"
}
or if you create classes that maps to the fields:
public class MyRequestModel {
private String userId;
private QueryResults queryResults;
}
public class QueryResults {
private String id;
private CarData carData;
private String carId;
private Integer status;
private String model;
}
or if you serialize it into something generic (not recommended):
public class MyRequestModel {
private String userId;
private Object queryResults;
}
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
public class MyRequestModel {
private String userId;
private JsonNode queryResults;
}
You have two options to deserialize this request:-
change the type of queryResults to Map<String, Object>, it will accepts everything as an object of key and value. (Not recommended)
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
You have to create a class that wraps the results of queryResults as an object.
class QueryResult {
private String id;
private Map<String, Object> carData;
private String carId;
private Integer status;
private String model;
public QueryResult() {}
public QueryResult(String id, Map<String, Object> carData, String carId, Integer status, String model) {
this.id = id;
this.carData = carData;
this.carId = carId;
this.status = status;
this.model = model;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, Object> getCarData() {
return carData;
}
public void setCarData(Map<String, Object> carData) {
this.carData = carData;
}
public String getCarId() {
return carId;
}
public void setCarId(String carId) {
this.carId = carId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
and make the type of queryResult as shown:-
public class MyRequestModel {
private String userId;
private QueryResult queryResults;
}

XML to JSON | Spring boot | Jackson

I am working on a Springboot project and fetching data from Rest API. The response is in XML format and I am facing difficulty while converting it to JSON
XML Response:
<StoreInfo>
<Store Number="1" NCPDPID="0411"/>
<Store Number="3" NCPDPID="1132"/>
<Store Number="4" NCPDPID="0407"/>
</StoreInfo>
The JSON classes I've created are:
public class IDResponse {
private List<IDInfo> StoreInfo;
}
public class IDInfo {
private List<Store> Store;
}
public class Store {
private Integer Number;
private String ID;
}
Code to fetch and convert:
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
ResponseEntity<String> response = restTemplate.exchange(requestUrl,
HttpMethod.GET, entity,
String.class);
XmlMapper xmlMapper = new XmlMapper();
responseData = xmlMapper.readValue(response, IDInfo.class);
The exception I am getting:
Method threw
'com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException'
exception.
Unrecognized field "Store" (class
com.walmart.datamodel.location.IDResponse), not marked as ignorable
How to fix this?
The uppercase names shouldn't be used in the Java classes.
Number and Id are attributes so you should use Annotatiaons to guide jackson:
Root
#JacksonXmlRootElement(localName = "StoreInfo")
public class IDResponse {
#JacksonXmlProperty(localName = "Store")
#JacksonXmlCData
#JacksonXmlElementWrapper(useWrapping = false)
private List<Store> storeInfo;
public List<Store> getStoreInfo() {
return storeInfo;
}
public void setStoreInfo(List<Store> storeInfo) {
this.storeInfo = storeInfo;
}
}
Store Element
public class Store {
#JacksonXmlProperty(localName="Number")
private Integer number;
#JacksonXmlProperty(localName="NCPDPID")
private String id;
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
IDInfo-class isn't needed.

JAX-RS Json response comes in one line

This is probably some basic question. I am using JAX-RS (jersey implementation) and my code is as follows.
#Path("/data")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Car handlerFn(#Context HttpServletResponse res)
{
res.setStatus(HttpServletResponse.SC_OK);
Car carObject = new Car(42,"Maruthi", "Alto");
return carObject;
}
Car Entity is as follows
public class Car {
int id;
String name;
String model;
public Car() {
}
public Car(int id, String name, String model)
{
this.id=id;
this.name = name;
this.model = model;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getModel() {
return model;
}
}
The output I am getting is in one line as follows
{"id":42,"model":"Alto","name":"Maruthi"}
In place of this I want the each member in different lines as follows
{
"id": 42,
"model": "Alto",
"name": "Maruthi"
}
How can I do that?

GluonConnect JSON converter cannot convert object

On the client app I have this POJO
public class Chicken {
private String name;
private int age;
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
and I run this
RestClient get = RestClient.create().method("GET")
.host("http://localhost:8080/DevCrowd")
.path("resources/chickens");
GluonObservableList<Chicken> sample = DataProvider.retrieveList(
get.createListDataReader(Chicken.class));
System.out.println(sample);
But I get the error:
WARNING: Failed to create object of type class com.devcrowd.test.Chicken from the following json object {"id":1,"name":"AAA","age":12}
java.lang.InstantiationException: com.gluonhq.notesapp.Chicken
at java.lang.Class.newInstance(Class.java:427)
at com.gluonhq.connect.converter.JsonConverter.readFromJson(JsonConverter.java:111)
at com.gluonhq.connect.converter.JsonIterableInputConverter.next(JsonIterableInputConverter.java:108)
at com.gluonhq.connect.provider.DataProvider.lambda$retrieveList$21(DataProvider.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodException: com.gluonhq.notesapp.Chicken.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 6 more
On the server I have this entity:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
#Entity
#NamedQuery(name="all", query = "SELECT c FROM Chicken C")
public class Chicken {
#Id
#GeneratedValue
private long id;
private String name;
private int age;
public Chicken() {}
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
}
and this service:
#Path("chickens")
public class ChickensResource {
#Inject
ChickenService cs;
#GET
#Produces(MediaType.APPLICATION_JSON)
public String chickens() {
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
List<Chicken> chickens = cs.getAllChickens();
chickens.stream().map(chicken -> Json.createObjectBuilder()
.add("name", chicken.getName())
.add("age", chicken.getAge())
.build())
.forEach(jsonArrayBuilder::add);
return jsonArrayBuilder.build().toString();
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void save(JsonObject chicken) {
String name = chicken.getString("name");
int age = chicken.getInt("age");
cs.save(new Chicken(name, age));
}
}
I can POST correctly (I check the DB and what I POST is there so this is why the error stack has a Chicken object ready) but I can't read it back. Why is that?
As you can read in the docs for JsonConverter::readFromJson:
Convert the provided JSON Object into a Java object. If a new instance could not be created from the specified targetClass in the constructor, then null will be returned.
The conversion works by inspecting all the property methods of the target class. A property method is any field that has both a getter and a setter method.
Now if you check your exception:
java.lang.InstantiationException: com.gluonhq.notesapp.Chicken
at java.lang.Class.newInstance(Class.java:427)
the reason becomes clear: the target class (com.gluonhq.notesapp.Chicken) can't be instantiated, because it looks for a parameterless constructor.
All you'll need to do is add one:
public class Chicken {
private String name;
private int age;
public Chicken() { }
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
...
}
EDIT
The DataProvider returns an observable list, and you should use the initializedProperty() to find out when the list is ready, so you can get its content:
RestClient get = RestClient.create().method("GET")
.host("http://localhost:8080/DevCrowd")
.path("/resources/chickens");
GluonObservableList<Chicken> sample = DataProvider.retrieveList(
get.createListDataReader(Chicken.class));
sample.initializedProperty().addListener((obs, ov, nv) -> {
if (nv) {
for (Chicken chicken : sample) {
System.out.println(chicken);
}
}
});