JSON deserialiser to set custom properties in POJO - java

I'm using Jackson for json mapping on java POJOs. What I want is to set two properties in POJO from a value in JSON by splitting the value.
{
"email": "xyz#hello.com",
}
and POJO is
public class TestPojo {
#JsonProperty("email")
private String emailAddress;
/*is there any annotation available that I can split the email
address with a delimiter which is '#' to first and second
properties*/
private String first; //gives value xyz
private String second;//gives value hello.com
}
Thanks for your help in advance.

You can hijack that logic in your public setter.
For instance:
class MyPojo {
// no need for this annotation here actually, covered by setter
// at least for deserialization
#JsonProperty
String email;
String first;
String last;
#JsonProperty("email")
public void setEmail(String email) {
this.email = email;
String[] split = email.split("#");
// TODO check length etc.
this.first = split[0];
this.last = split[1];
}
// just for testing
#Override
public String toString() {
return String.format(
"email: %s, first: %s, last: %s%n", email, first, last
);
}
}
Then, somewhere else...
String json = "{ \"email\": \"xyz#hello.com\"}";
ObjectMapper om = new ObjectMapper();
MyPojo pojo = om.readValue(json, MyPojo.class);
System.out.println(pojo);
Output
email: xyz#hello.com, first: xyz, last: hello.com

Related

how to convert json?

I want to convert firstname and lastname to json format.
#RestController
public class studentsController {
#GetMapping(value = "/students", produces = { MediaType.APPLICATION_JSON_VALUE } )
#ResponseBody
public String getWhoami(#RequestParam String firstname, #RequestParam String lastname ) {
return "firstname:" + firstname + " lastname: " + lastname;
}
}
How can I convert like these format;
{"firstname": "value1", "lastname": "value2"}
I tried to jackson but I couldn't.
You don't have to create json manually.
Create a class like:
class Student {
private String firstname;
private String lastname;
public Student(String firstname, String lastname) {
this.firstname = firstname;
this.lastname =lastname;
}
// getters and setter
}
#GetMapping(value = "/students", produces = { MediaType.APPLICATION_JSON_VALUE } )
#ResponseBody
public Student getWhoami(#RequestParam String firstname, #RequestParam String lastname ) {
return new Student(firstname, lastname);
}
You object will be converted to json automatically.
have you tried the jackson like this?
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
add in your class an instance like this:
ObjectMapper mapper = new ObjectMapper();
private ObjectMapper mapper = new ObjectMapper();
try function from the instance like this:
String jsonstr = mapper.writeValueAsString(object);
Lets say you already have the jackson library in your project (the jar file)
here's sample class:
public class SampleClass{
private ObjectMapper mapper = new ObjectMapper();
public String sampleMethodToJSONString(Student student){
return mapper.writeValueAsString(student);
}
}
You can change the return data type to use Map<String, String> instead of String or use ResponseBody<?>

Return part of JSON into object Spring boot

I have JSON structure that goes like this
{
"name":"John",
"age":27,
"company":{
"company_name":"ACME LLC",
"address": "1st Street",
"country": "US"
}
}
I know that if I want to map this to java object I need some kind of mapper and I have done that.
My question is: Is there a way to map only part of this json into object. I would like to map only company part of json into object. One more thing, I'm using java 11 with spring boot and I have access to Jackson's Object mapper.
Edit: Also if there is a way to navigate to this object it would be ok. For example $.company
I think the easiest way is to create two model classes. First with one field:
#Data
public class Model {
private Company company;
}
and second:
#Data
public class Company {
#JsonProperty("company_name")
private String companyName;
private String address;
private String country;
}
Then you can use Jackson mapper. You don't need to mention "map" and "age" fields in the Model class.
Ok, I have found an answer, thank you #Jakub on your answer it was a great help. Link to comment.
This is code example of answer based on my question:
public class Company {
private String name;
private String address;
private String country;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Test method/execution:
#Test
public void testJSON() throws JsonProcessingException {
JsonNode productNode = objectMapper.readTree("{\n" +
" \"name\":\"John\",\n" +
" \"age\":27,\n" +
" \"company\":{\n" +
" \"name\":\"ACME LLC\",\n" +
" \"address\": \"1st Street\",\n" +
" \"country\": \"US\"\n" +
" }\n" +
"}");
Company company = objectMapper.readValue(productNode.get("company").toString(), Company.class);
System.out.println(company.getAddress());
}
I would suggest using DSM library.
define your mapping in yaml file, you only want to company field. So your mapping file will be like below.
result:
type: object
path: /company
fields:
name: # read value from field in path
path: company_name
address: #field name is the same
country:
Java code to read file:
DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).create();
Map<String,Object> result= ( Map<String,Object>)dsm.toObject(jsonData);
result is a map that contains information in company field in json.
If you want to directly get instance of the class by deserialization:
public class Company{
String name;
String address;
String country;
}
Java code to deserialize:
DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).create();
Company result= dsm.toObject(jsonData,Company.class);

How to get Jackson mixin to handle an included type?

I'm using Jackson mixins to only serialize out specific fields.
My ObjectMapper is configured like so:
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.addMixIn(Person.class, SyncPerson.class);
mapper.addMixIn(TransactionLog.class, TransactionLogExport.class);
Here are the model classes paired with the JSON mixin objects that I'd like to export:
// Model class
public class Person {
private Long id;
private String email;
private String firstName;
private String lastName;
}
// Desired JSON format. Excludes 'id' field
public interface SyncPerson {
#JsonProperty("firstName")
String getFirstName();
#JsonProperty("lastName")
String getLastName();
#JsonProperty("email")
String getEmail();
}
// Model class
public class TransactionLog {
private long id;
private Integer version;
private Person person;
private Date date;
private EntityAction action;
}
// Desired JSON format. Excludes 'id' field, 'version', 'date'
public interface TransactionLogExport {
#JsonProperty("id")
String getId();
#JsonProperty("person")
Person person();
#JsonProperty("action")
EntityAction getAction();
}
Yet, my tests are showing that the person attribute of the TransactionLog isn't coming through.
#Test
public void testWriteValue() throws Exception {
Person person = new Person();
person.setEmail("a#c.com");
person.setFirstName("A");
person.setLastName("C");
TransactionLog log = new TransactionLog();
log.setId(0L);
log.setAction(EntityAction.CREATE);
log.setPerson(person);
log.setStartValue("start");
log.setEndValue("end");
log.setChanges("change");
String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(log);
System.out.println(prettyJson);
// Prints:
// {
// "id" : 0,
// "action" : "CREATE",
}
}
If I try the same test with a regular ObjectMapper mapper = new ObjectMapper(); instead of the mixin, then I see the full object exported, including the Person with email, names, etc. So something must be wrong with how I've configured the mixin... or else I'm misunderstanding something.
So can anyone help indicate what I could do to export out the subtype 'person' in my mixin?
Thanks!
Finally figured out the issue. The test now prints what we want:
{
“id” : 0,
“person” : {
“email” : “a#c.com”,
“firstName” : “A”,
“lastName” : “C”
},
“action” : “CREATE”
}
The mistake was in TransactionLogExport. It needs to say:
#JsonProperty("person")
Person getPerson();
Instead of:
#JsonProperty("person")
Person person();
I.e. the method needs to start with 'get'.

How to store values using Jackson JSON to Java

I am having a really hard time understanding how to place a mapped valued into an array and how to iterate that array.
test.json
[
{
"Name": "Bob",
"Nationality": "",
"City": "Chicago",
"Phone" : "451232424234"
},
......continues with more objects
]
testTemplate.java
//imports
#JSONInclude(Json.Include.Non_NULL)
#JsonPropertyOrder({"Name,"Nationality","City","Phone"})
Public class testTemplate {
#JsonProperty("Name")
private String userName;
#JsonProperty("Nationality")
private String nation;
#JsonProperty("City")
private String city;
#JsonProperty("Phone")
private String phone;
#JsonProperty("Name")
public String getName (String userName) {
this.userName = userName;
}
#JsonProperty("Nationality")
public String nation (String nation) {
this.nation = nation;
}
#JsonProperty("City")
public String city (String city) {
this.city = city;
}
#JsonProperty("Phone")
public String phone (String phone) {
this.phone = phone;
}
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
testParse.java
Public Class testParse {
List<testParse> test;
ObjectMapper mapper;
protected void setUp() throws IOException {
mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT();
test = mapper.readValue(this.getClass().getResourcesAsStream("test.json"),
mapper.getTypeFactory().constructCollectionType(List.class, testParse.class));
I need to help first clarifying exactly what the code is doing, and how to put JSON properties (Name, Nationality,City,Phone) into Java.
My understanding is the testTemplate file create the strings in which the properties will be held, then the testParse file has the mapper feature (from Jackson) that reads through the json and puts all into "test" (as an array?)
My goal is in testParse, where if everything thing is in "test", then I read through that, and start to pull it out and place it into a folderList.
public static Map<String, String> userName throws IOException {
Map<String, String> folderList = new TreeMap<>();
//Don't know how, but iterate through "test"
LineIterator it = new LineIterator(//the method used to read the json file);
try {
while(it.hasNext()) {
String line = it.nextLine();
folderList.put(userName,nation) //can I also put city and phone at once as well or should I create another put: folderList.put(userName, city)
return folderList;
How does one do this? Is there a better way to put the properties of json into the folderList after using the jackson mapper?
Actually, testTemplate don't generate anything, what Jackson have done here is just get data from "test.json" as String, then using Reflection read the format of testTemplate.java. Based on template it've just have + setting you add to ObjectMapper object, Jackson will convert test.json to array of object Java.
P/S: you don't need to add annotation in both attributes and get function of POJO class, just do it in get function or attributes only, it's enough for Jackson.

Java - Jackson JSON Library and ObjectMapper.readValue

I have the following json data (patients.json):
{
"A" : {
"name" : "Tom",
"age" : 12
},
"B" : {
"name" : "Jim",
"age" : 54
}
}
Using the Jackson JSON library, how can I get something like the following:
HashMap<String, ???> patients = objectMapper.readValue(new File("patients.json"), ???);
String Aname = patients.get("A").get("name");
int Aname = patients.get("A").get("age");
Deserialize your JSON into Jackson's JSON Object type, ObjectNode. You can then traverse it as you see fit.
For example
ObjectNode patients = objectMapper.readValue(new File("test.json"), ObjectNode.class);
// you can check if it is actually an ObjectNode with JsonNode#isObject()
ObjectNode nodeA = (ObjectNode)patients.get("A");
String name = nodeA.get("name").asText();
int age = (int) nodeA.get("age").asLong();
Note that the methods asXyz() return default values if the target node cannot be converted to that type. You can check with the corresponding isXyz() methods before invoking them.
You could create a class to map your patients to;
private static class Patient {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
public Patient() { }
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Then read your json into it via jackson
HashMap<String, Patient> patients = objectMapper.readValue(new File("patients.json"), new TypeReference<HashMap<String,Patient>>() {});
Patient patientA = patients.get("A");
String patientAName = patientA.getName();
int pateintAAge = patientA.getAge();

Categories