I want to create below JSON payload
{
"maxResults":3,
"counter":0,
"customerParameters":{
"filters":[
{
"name":"customerId",
"operator":"=",
"value":["hello"]
}
]
},
"dealerParameters":[
{
"name":"club"
},
{
"name":"token"
}
]
}
Coded so far:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"maxResults",
"counter",
"customerParameters",
"dealerParameters"
})
public class CustomerModel {
#JsonProperty("maxResults")
private Integer maxResults;
#JsonProperty("counter")
private Integer counter;
#JsonProperty("customerParameters")
private CustomerParameters customerParameters;
#JsonProperty("dealerParameters")
private List<DealerParameter> dealerParameters = null;
#JsonProperty("customerParameters")
public CustomerParameters getCustomerParameters() {
return customerParameters;
}
#JsonProperty("customerParameters")
public void setCustomerParameters(CustomerParameters customerParameters) {
this.customerParameters = customerParameters;
}
#JsonProperty("dealerParameters")
public List<DealerParameter> getDealerParameters() {
return dealerParameters;
}
#JsonProperty("dealerParameters")
public void setDealerParameters(List<DealerParameter> dealerParameters) {
this.dealerParameters = dealerParameters;
}
// Getter/Setter for other params
}
CustomerParameters.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"filters"
})
public class CustomerParameters {
#JsonProperty("filters")
private List<Filter> filters = null;
// Setter and Getter for filters parameter
}
DealerParameters.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"name"
})
public class DealerParameter {
#JsonProperty("name")
private String name;
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
}
Filter.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"name",
"operator",
"value"
})
public class Filter {
#JsonProperty("name")
private String name;
#JsonProperty("operator")
private String operator;
#JsonProperty("value")
private List<String> value = null;
#JsonProperty("value")
public List<String> getValue() {
return value;
}
#JsonProperty("value")
public void setValue(List<String> value) {
this.value = value;
}
// Setter and Getter for other properties
}
Missing Part:
#Controller
public class TestContoller {
RestTemplate restTemplate;
Should I instantiate each pojo class with new operator as below and set all required parameters ? or any other approach of creating JSON payload?
CustomerModel customerModel= new CustomerModel();
customerModel.setMaxResults(1);
Filter filter= new Filter();
filter.setName("customerID");
filter.setOperator("-");
filter.setValue(Arrays.asList("club"));
CustomerParameters customerParameters = new CustomerParameters();
customerParameters.setFilters(Arrays.asList(filter));
customerModel.setCustomerParameters(customerParameters);
For DealerParameter class, I want to create multiple objects with same key different value(see the json payload I mentioned above). Below code creates only one object "name":"dealerId"
DealerParameter dealerParameter = new DealerParameter();
dealerParameter.setName("dealerId");
customerModel.setDealerParameters(dealerParameter);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValueAsString(customerModel);
restTemplate.exchange(todo); // restful service call
}
you are already using "ObjectMapper", And ObjectMapper has readValue() method. By using readValue() method you can populate all data at a time like below:--
ObjectMapper objectMapper = new ObjectMapper();
//populating data from json string to POJO
CustomerModel customerModel = objectMapper.readValue(<json String>,CustomerModel.class);
System.out.println(objectMapper.writeValueAsString(customerModel); // print all data
Related
in Microservice, we post multiple dtos data as string json.
Controller:
#RequestMapping(value="/json",method = RequestMethod.POST)
public String getjson(#RequestBody String json) {
///Service process
}
Post Json:
{
"dtos":{
"Dto1":{
"name":"Dto1 Name Field",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10}
]
},
"Dto2":{
"city":"Newyork",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10},
{"key":"f3","value":10}
]
}
},
"page":1
}
DTO:
public class Dto1{
private String name;
}
public class Dto2{
private String city;
}
Dto1 and Dto2 is java DTO object name.
how to convert string json to java objects?
You can create a new DTO that contains all attrs and receive in request:
public class Filter{
private String key;
private int value;
}
public class Dto1{
private String name;
private List<Filter> filter;
}
public class Dto2{
private String city;
private List<Filter> filter;
}
public class Dtos{
public Dto1 dto1;
public Dto2 dto2;
}
public class DtoToReceiveInRequest{
private Dtos dtos;
private int page;
}
Controller
#PostMapping
public String getjson(#RequestBody DtoToReceiveInRequest json) {
///Service process
}
You can use the ObjectMapper from the jackson library, like below.
String json = "";
ObjectMapper objectMapper = new ObjectMapper();
Dto1 dto = objectMapper.readValue(json, Dto1.class);
But in your particular example, you don't have to have two DTO classes. You can encapsulate values in one DTO and have the list of different instances of that DTO in a json format.
NB. The json string should be a representation of the preferred class you want to retrieve, eg Dto1.java.
I have the following json
{
"root": {
"status": "UP",
"connection1": {
"status": "UP"
},
"connection2": {
"status": "UP"
}
}
}
Also i have the following POJO classes i want to convert JSON into
#JsonIgnoreProperties(ignoreUnknown = true)
public class POJO {
#JsonProperty("root")
#JsonDeserialize(using = RootDeserializer.class)
private Root root;
//getters + setters
}
public class Root {
private boolean isAlive;
private List<Connection> connections;
public Root(boolean isAlive, List<Connection> connections) {
this.isAlive = isAlive;
this.connections = connections;
}
//getters + setters
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Connection {
private String status;
//getters + setters
}
And finally i have this deserializer to convert json into Root instance
public class RootDeserializer extends JsonDeserializer<Root> {
private static final String CONNECTION_PREFIX = "connection";
private static final String UP_STATUS = "UP";
private ObjectMapper objectMapper = new ObjectMapper();
#Override
public Root deserialize(JsonParser parser, DeserializationContext context) throws IOException {
Map<String, Map<String, Object>> rootJsonMap = parser.readValueAs(Map.class);
boolean isAlive = StringUtils.equals(UP_STATUS, String.valueOf(rootJsonMap.get("status")));
List<Connection> connections = rootJsonMap.entrySet()
.stream()
.filter(entry -> StringUtils.startsWithIgnoreCase(entry.getKey(), CONNECTION_PREFIX))
.map(this::mapToConnection)
.collect(Collectors.toList());
return new Root(isAlive, connections);
}
private PosServerConnection mapToConnection(Map.Entry<String, Map<String, Object>> entry) {
Map<String, Object> connectionJsonMap = entry.getValue();
return objectMapper.convertValue(connectionJsonMap, Connection.class);
}
}
This way i can group all my Connections into one List in Root class.
My question is there any another way to do this ??
I'd like to do this without such big deserializer using just Jackson annotations on my Pojo classes
You can simply achieve this by using #JsonAnySetter annotation for customizing Setter for List<Connection> as follows. You can also reference to Jackson Annotation Examples to see how it works.
POJOs
public class Pojo {
private Root root;
//general getters, setters and toString
}
public class Root {
private String status;
private List<Connection> connections = new ArrayList<>();
public List<Connection> getConnections() {
return connections;
}
#JsonAnySetter
public void setConnections(String name, Connection connection) {
connection.setName(name);
this.connections.add(connection);
}
//other getters, setters and toString
}
public class Connection {
private String name;
private String status;
//general getters, setters and toString
}
Then you can serialize the given JSON string to Pojo with common way by Jackson:
Code Snippet
ObjectMapper mapper = new ObjectMapper();
Pojo pojo = mapper.readValue(jsonStr, Pojo.class);
System.out.println(pojo.getRoot().getConnections().toString());
Console output
[Connection [name=connection1, status=UP], Connection [name=connection2, status=UP]]
I have an endpoint in spring boot that consumes this JSON as an example:
{
"userId": 3,
"postBody": "This is the body of a post",
"postTitle": "This is the title of a post",
"created": null,
"tagList": ["tag1", "tag2", "tag3"]
}
The endpoint:
#RequestMapping(value="/newPost", method = RequestMethod.POST, produces="application/json", consumes = "application/json")
#ResponseBody
public ResponseEntity newPost(#RequestBody Map<String, Object> body) throws Exception {
I know the issue here is the Request body is being saved as a Map of objects which is fine for all the other attributes except the tagList. How can I get tagList to be an array of Strings in Java?
Thanks.
A mixutre of Ankur and Jose's answers solved this, thanks for the fast responses guys!
You should probably create a Java class which represents the input JSON and use it in the method newPost(.....). For example:-
public class UserPostInfo {
private int userId;
private String postBody;
private String postTitle;
private Date created;
private List<String> tagList;
}
Also, include the getter/setter methods in this class.
If you want to modify the behavior of JSON parsing, you can use Annotations to change field names, include only non-null values, and stuff like this.
If you don't want to use a custom POJO you could also just handle the deserialization into a Map yourself. Just have your controller accept a String and then use Jackson's ObjectMapper along with TypeReference to get a map.
#RequestMapping(value="/newPost", method = RequestMethod.POST, produces="application/json", consumes = "application/json")
#ResponseBody
public ResponseEntity newPost(#RequestBody String body) throws Exception {
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {};
HashMap<String,Object> map = mapper.readValue(body, typeRef);
}
The resulting HashMap will use an ArrayList for the tag list:
You can create a custom Java POJO for the request that uses String[] versus List<String>. Here I did it for you using the site jsonschema2pojo.
package com.stackoverflow.question;
import com.fasterxml.jackson.annotation.*;
import java.util.HashMap;
import java.util.Map;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"userId",
"postBody",
"postTitle",
"created",
"tagList"
})
public class MyRequest {
#JsonProperty("userId")
private int userId;
#JsonProperty("postBody")
private String postBody;
#JsonProperty("postTitle")
private String postTitle;
#JsonProperty("created")
private Object created;
#JsonProperty("tagList")
private String[] tagList = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("userId")
public int getUserId() {
return userId;
}
#JsonProperty("userId")
public void setUserId(int userId) {
this.userId = userId;
}
#JsonProperty("postBody")
public String getPostBody() {
return postBody;
}
#JsonProperty("postBody")
public void setPostBody(String postBody) {
this.postBody = postBody;
}
#JsonProperty("postTitle")
public String getPostTitle() {
return postTitle;
}
#JsonProperty("postTitle")
public void setPostTitle(String postTitle) {
this.postTitle = postTitle;
}
#JsonProperty("created")
public Object getCreated() {
return created;
}
#JsonProperty("created")
public void setCreated(Object created) {
this.created = created;
}
#JsonProperty("tagList")
public String[] getTagList() {
return tagList;
}
#JsonProperty("tagList")
public void setTagList(String[] tagList) {
this.tagList = tagList;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
I'm new to Jackson. I've tried to parse Json string to an object but jackson returns an object with all null values. Here is code of my parser:
ObjectMapper mapper = new ObjectMapper();
FullTextRetrievalResponse object =
mapper.readValue(response.getBody().getObject().toString(),
FullTextRetrievalResponse.class);
Here is my FullTextRetrievalResponse class:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"coredata",
"scopus-id",
"scopus-eid",
"link",
"originalText"
})
public class FullTextRetrievalResponse {
#JsonProperty("coredata")
private Coredata coredata;
#JsonProperty("scopus-id")
private String scopusId;
#JsonProperty("scopus-eid")
private String scopusEid;
#JsonProperty("link")
private Link_ link;
#JsonProperty("originalText")
private OriginalText originalText;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("coredata")
public Coredata getCoredata() {
return coredata;
}
#JsonProperty("coredata")
public void setCoredata(Coredata coredata) {
this.coredata = coredata;
}
#JsonProperty("scopus-id")
public String getScopusId() {
return scopusId;
}
#JsonProperty("scopus-id")
public void setScopusId(String scopusId) {
this.scopusId = scopusId;
}
#JsonProperty("scopus-eid")
public String getScopusEid() {
return scopusEid;
}
#JsonProperty("scopus-eid")
public void setScopusEid(String scopusEid) {
this.scopusEid = scopusEid;
}
#JsonProperty("link")
public Link_ getLink() {
return link;
}
#JsonProperty("link")
public void setLink(Link_ link) {
this.link = link;
}
#JsonProperty("originalText")
public OriginalText getOriginalText() {
return originalText;
}
#JsonProperty("originalText")
public void setOriginalText(OriginalText originalText) {
this.originalText = originalText;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
and here is part of JSON:
{
"full-text-retrieval-response": {
"coredata": {
"prism:url": "http://api.elsevier.com/content/article/pii/S1751157716302140",
"dc:identifier": "doi:10.1016/j.joi.2016.11.002",
"eid": "1-s2.0-S1751157716302140",
"prism:doi": "10.1016/j.joi.2016.11.002",
"pii": "S1751-1577(16)30214-0",
"dc:title": "The specific shapes of gender imbalance in scientific authorships: A network approach ",
"prism:publicationName": "Journal of Informetrics",
"prism:aggregationType": "Journal",
"prism:issn": "17511577",
"prism:coverDate": "2017-02-28",
"prism:coverDisplayDate": "February 2017",
"openaccess": "0",
"openaccessArticle": false,
"openaccessType": null,
"openArchiveArticle": false,
"openaccessSponsorName": null,
"openaccessSponsorType": null,
"openaccessUserLicense": null,
"link": [
{
"#rel": "self",
"#href": "http://api.elsevier.com/content/article/pii/S1751157716302140",
"#_fa": "true"
},
{
"#rel": "scidir",
"#href": "http://www.sciencedirect.com/science/article/pii/S1751157716302140",
"#_fa": "true"
}
]
}
}
}
The issue is that in your json object you have the field full-text-retrieval-response wrapping all your object, but in your java classes, the FullTextRetrievalResponse is the root.
I think you have 3 options
Change the json structure (supposing you can do that), removing the full-text-retrieval-response label (https://pastebin.com/MtxXSeDW)
Create a new class having an instance of FullTextRetrievalResponse as a json property:
public class FullTextRetrievalResponseWrapper {
#JsonProperty("full-text-retrieval-response")
private FullTextRetrievalResponse fullTextRetrievalResponse;
//setters and getters
}
And then make the serialization using this new class: mapper.readValue(response.getBody().getObject().toString(),
FullTextRetrievalResponseWrapper .class);
Create a custon json deserializer (http://www.baeldung.com/jackson-deserialization) to convert yourself the json object to your class.
Just another quick tip: if you are defining a field as a json property (#JsonProperty), you do not need to define the #JsonSetter, #JsonGetter or even the #JsonProperty in the setters and getters.
Simply I have a POJO like this:
#JsonInclude(value=Include.NON_EMPTY)
public class Contact {
#JsonProperty("email")
private String email;
#JsonProperty("firstName")
private String firstname;
#JsonIgnore
private String subscriptions[];
...
}
When I create the JSON object using the JsonFactory and ObjectMapper, it would be something like:
{"email":"test#test.com","firstName":"testName"}
Now, the question is how can I generate something like the following without manual mapping.
{"properties": [
{"property": "email", "value": "test#test.com"},
{"property": "firstName", "value": "testName"}
]}
Note that, I know how to do manual mapping. Also, I need to use some features like Include.NON_EMPTY.
You can implement two steps processing as follows.
Firstly, you convert your bean instance to a JsonNode instance using ObjectMapper. This guaranties applying all the Jackson annotations and customization. Secondly, you manually map the JsonNode fields to your "property-object" model.
Here is an example:
public class JacksonSerializer {
public static class Contact {
final public String email;
final public String firstname;
#JsonIgnore
public String ignoreMe = "abc";
public Contact(String email, String firstname) {
this.email = email;
this.firstname = firstname;
}
}
public static class Property {
final public String property;
final public Object value;
public Property(String property, Object value) {
this.property = property;
this.value = value;
}
}
public static class Container {
final public List<Property> properties;
public Container(List<Property> properties) {
this.properties = properties;
}
}
public static void main(String[] args) throws JsonProcessingException {
Contact contact = new Contact("abc#gmail.com", "John");
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.convertValue(contact, JsonNode.class);
Iterator<String> fieldNames = node.fieldNames();
List<Property> list = new ArrayList<>();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
list.add(new Property(fieldName, node.get(fieldName)));
}
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new Container(list)));
}
}
Output:
{ "properties" : [ {
"property" : "email",
"value" : "abc#gmail.com"
}, {
"property" : "firstname",
"value" : "John"
} ] }
With a little effort you can re-factor the example to a custom serializer which can be plugged as documented here.