I have a controller that receives a JSON RequestBody like the one below:
{
"status":"pending",
"status1":"pending",
"status2":"pending",
"status3":"pending",
"specs":{
"width":1000,
"height":1507,
........some other fields, any number of fields..
},
}
I have an Entity
#Entity
public class MyBean implements Serializable {
#Id
#GeneratedValue
Long id;
public String status;
public String status1;
public String status2;
public String status3;
}
and my Controller class:
#RequestMapping(value = "/insert", method = RequestMethod.POST)
public void insert(#RequestBody MyBean myBean) {
return myService.save(myBean);
}
My problem is that I want to store the value of specs (which is a JSON document) as a String in a Lob field and I don't know how to do that.
Declare specs as public Map<String,Integer> specs;
and to convert Object to json use Jackson fasterxml api as below
MyBean bean=new MyBean();
bean.setId(new Long(1));
bean.setStatus("pending");
bean.setStatus1("pending");
bean.setStatus2("pending");
bean.setStatus3("pending");
Map<String, Integer> temp=new HashMap<String, Integer>();
temp.put("width",1000);
temp.put("height",1507);
bean.setSpecs(temp);
//Object to json
StringWriter sw=new StringWriter();
ObjectMapper mapper=new ObjectMapper();
mapper.writeValue(sw,bean);
System.out.println(sw.toString());
//json to object
MyBean newBean=mapper.readValue(sw.toString(), MyBean.class);
System.out.println(newBean.toString());
If you want serialize only specs before saving then use same mapper.writeValue() function to convert specs to json string
for more information refer this
Related
I'm having trouble finding a way to convert a CSV file which contains some JSON Arrays and JSON objects to Java Pojos using OpenCSV. (I'm open to other 3rd party libraries if they can handle this better.)
Example CSV data:
id, customers
5 [{"name":"bob", "age": 90}]
Example POJO data:
#Data
#NoArgsConstructor
public class Links {
#CsvBindByName
private int id;
#CsvBindByName
private List<Customer> customers;
}
#Data
#NoArgsConstructor
public class Customer {
#CsvBindByName
private String name;
#CsvBindByName
private int age;
}
I feel like a custom convert might be needed something like below. But cannot get it working.
#CsvBindAndSplitByName(elementType= Customer.class, converter = TextToCustomer.class)
#Override
public List<Customer> convertToRead(String value) {
Gson gson = new Gson();
List<Customer> customers;
Type listType = new TypeToken<List<Customer>>() {
}.getType();
contacts = new Gson().fromJson(value, listType);
return customers;
}
#Override
public String convertToWrite(Object value) {
JSONArray t = (JSONArray) value;
return String.format(t.toJSONString());
}
My question is kind of similar to Prevent GSON from serializing JSON string but the solution there uses GSON library and I am restricted to using Jackson (fasterxml).
I have an entity class as follows:
package com.dawson.model;
import com.dawson.model.audit.BaseLongEntity;
import lombok.extern.log4j.Log4j;
import javax.persistence.*;
#Table(name = "queue", schema = "dawson")
#Entity
#Log4j
public class Queue extends BaseLongEntity {
protected String requestType;
protected String body;
protected Queue() {
}
public Queue(String requestType, String body) {
this.requestType = requestType;
this.body = body;
}
#Column(name = "request_type")
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
#Column(name = "body")
#Lob
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
I want to populate the body field with the json string representation of a map and then send this as part of the ResponseEntity. Something as follows:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.writer().withDefaultPrettyPrinter();
HashMap<String, String> map = new HashMap<>(5);
map.put("inquiry", "How Can I solve the problem with Jackson double serialization of strings?");
map.put("phone", "+12345677890");
Queue queue = null;
try {
queue = new Queue("General Inquiry", mapper.writeValueAsString(map));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
String test = mapper.writeValueAsString(map)
System.out.println(test);
Expected Output: "{"requestType": "General Inquiry","body": "{"inquiry":"How Can I solve the problem with Jackson double serialization of strings?","phone":"+12345677890"}"}"
Actual Output:"{"requestType": "General Inquiry","body": "{\"inquiry\":\"How Can I solve the problem with Jackson double serialization of strings?\",\"phone\":\"+12345677890\"}"}"
I am using
Jackson Core v2.8.2
I tried playing with
#JsonIgnore
and
#JsonProperty
tags but that doesn't help because my field is already serialized from the map when writing to the Entity.
Add the #JsonRawValue annotation to the body property. This makes Jackson treat the contents of the property as a literal JSON value, that should not be processed.
Be aware that Jackson doesn't do any validation of the field's contents, which makes it dangerously easy to produce invalid JSON.
Currently I'm working on spring project and I want to display class as a JSON response. Following is the class template and other related details.
public class Country {
#Column(name = "name")
private String name;
#Id
#Column(name = "code")
private String Code;
//Getters & Setters ...
}
current response :
[{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}]
Expected response :
[ { "countries" : [{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}], "status" : "ok", "message":"success", etc..etc...}]
instead of status and message, it could be some array list too.
You need create class contain list and use ResponseEntity.
public class Foo {
private List<Country> countries;
// get/set...
}
#Controller
public class MyController {
#ResponseBody
#RequestMapping(value = "/foo", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public ResponseEntity<Foo> foo() {
Foo foo = new Foo();
Country country = new Country();
foo.getCountries().add(country);
return ResponseEntity.ok(foo);
}
}
You should create another object, e.g. called Countries as shown below:
public class Countries {
private List<Country> countries;
// getters & setters
}
or:
public class Countries {
private Country[] countries;
// getters & setters
}
The list or array of Country objects will map to your expected {"countries" : [{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}]}, because the JSON {} refers to some object and [] refers to list/array in Java code.
Actually you can also achieve using jackson library.
//Create obj of ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//Get the Json string value from the mapper
String json = mapper.writeValueAsString(obj)
And then return this json string in your controller method.
The advantage of using this is that, you can also ignore certain fields in the POJO for JSON conversion using #JsonIgnore annotation (Put this annotation before the getter of the field that you want to ignore) (Not sure if you can do the same from Spring ResponseEntity.
Note: Please correct me if I am wrong anywhere.
I have the following JSON:
{
"data": {
"1": {
"id":"1",
"name":"test1"
},
"2": {
"id":"2",
"name":"test2"
}
}
}
I want to parse the "data" into an Object with Jackson. If I parse it as Map<String, Object> it works well, whereas "1", "2" (...) are used as Key with the respective data as value, represented by a Map again.
Now I want to parse this JSON to Map<String, TypeA> whereas class TypeA would have two fields, id and name.
Can someone give me a hint how to to that?
I always get the following error:
Could not read JSON: No suitable constructor found for type [simple
type, class TypeA]: can not instantiate from JSON object (need to
add/enable type information?)
Thanks a lot in advance,
tohoe
The following should work out for you.
public class MyDataObject {
private final Map<String, TypeA> data;
#JsonCreator
public MyDataObject(#JsonProperty("data") final Map<String, TypeA> data) {
this.data = data;
}
public Map<String, TypeA> getData() {
return data;
}
}
public class TypeA {
private final String id;
private final String name;
#JsonCreator
public TypeA(#JsonProperty("id") final String id,
#JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
The #JsonCreator is used for describing how to create your objects together with the name of the properties #JsonProperty. Even if they are nested.
To deserialize the whole thing:
ObjectMapper mapper = new ObjectMapper();
final MyDataObject myDataObject = mapper.readValue(json, MyDataObject.class);
I want to deserialize the following JSON object:
{
"id":"001",
"module_name":"Users",
"name_value_list":
{
"user_name": {"name":"user_name", "value":"admin"},
"full_name": {"name":"full_name", "value":"LluĂs Pi"},
"city": {"name":"full_name", "value":"Barcelona"},
"postal_code": {"name":"postal_code", "value":"08017"},
...
}
}
into some Java object like this:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class UserEntry
{
private String id;
private String moduleName;
private Person nameValueList;
public String getId()
{
return id;
}
public String getModuleName()
{
return moduleName;
}
public Person getPerson()
{
return nameValueList;
}
}
where Person is the following class:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
class Person
{
private String userName;
private String fullName;
private String city;
private String postalCode;
}
using Jackson but I get a deserialization error.
If I change the type of field nameValueList to a Map all the deserialization process goes with no problem and I get a map where the key is the "name" value and the value is the "value" value.
So my question is: is there any simple, or no so simple, way to deserialize this kind of JSON object to a Java Pojo with properties prop_1, prop_2, prop_3and prop_4?
{
"name_value_list":
{
"prop_1": {"name":"prop_1", "value":"value_1"},
"prop_2": {"name":"prop_2", "value":"value_2"},
"prop_3": {"name":"prop_3", "value":"value_3"},
"prop_4": {"name":"prop_4", "value":"value_4"},
...
}
}
Not very simple and not very clean. However you can do it by implementing a any setter field for the JSON attributes in the Person class which don't match any attribute on your UserEntry POJO.
#JsonAnySetter
public void putUserField(String userKey, Map<String, String> userValue)
throws NoSuchFieldException {
String actualFieldName = getActualFieldName(userKey);
Field field = this.getClass().getDeclaredField(actualFieldName);
field.setAccessible(true);
ReflectionUtils.setField(field, this, userValue.get("value"));
}
private String getActualFieldName(String userKey) {
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, userKey);
}
In addition to that, I had to change the Jackson attributes for the Person class to
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
getterVisibility = JsonAutoDetect.Visibility.NONE)
for it to work for attributes like "city" which don't need any name transformation because jackson tries to directly set the field which fails.