how to convert json? - java

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<?>

Related

De-serialize a POJO using Lombok to send large JSON payload

I'm a QA writing some tests using Rest Assured DSL.
This is my first attempt at using Lombok to deserialize a POJO for use in the JSON Payload.
This way of building my data object, Customer, seems very cumbersome. As the test is failing with a 400, I assume I am not serializing it correctly and I'm unclear how to view the payload as JSON.
I'm not using an explicit mapping, so assume Rest Assured is using GSON by default.
Given my POJO:
import lombok.Data;
#Data
public class Customer {
private String employeeCode;
private String customer;
private String firstName;
private String lastName;
private String title;
private String dob;
private String employeeId;
}
...And example payload I need to send:
{
"employeeCode": "18ae56",
"customer": {
"firstName": "John",
"lastName": "Smith",
"title": "Mr",
"dob": "1982-01-08",
"employeeId": "2898373"
}
}
My example test is:
#BeforeClass
public static void createRequestSpecification(){
requestSpec = new RequestSpecBuilder()
.setBaseUri("https://employee-applications.company.com")
.setContentType(ContentType.JSON)
.build();
}
#Test
public void createApplicationForNewCustomer(){
Customer customer = Customer.builder().build();
customer.setEmployeeCode("18ae56");
customer.setFirstName("John");
customer.setLastName("Smith");
customer.setTitle("Mr");
customer.setDob("1982-01-08");
customer.setEmployeeId("2898373");
given().
spec(requestSpec).
and().
body(customer).
when().
post("/api/v6/applications").
then().
assertThat().statusCode(201);
}
Your POJO is incorrect and obviously the serialized JSON is not of the expected format
You should have two classes
Below is how your POJO should look like to generate the given JSON structure
#Data
public static class Customer {
#JsonProperty("firstName")
private String firstName;
#JsonProperty("lastName")
private String lastName;
#JsonProperty("title")
private String title;
#JsonProperty("dob")
private String dob;
#JsonProperty("employeeId")
private String employeeId;
}
#Data
public static class Example {
#JsonProperty("employeeCode")
public String employeeCode;
#JsonProperty("customer")
public Customer customer;
}
and your test method
Example e = new Example();
e.setEmployeeCode("18ae56");
Customer c = new Customer();
c.setFirstName("John");
c.setLastName("Smith");
c.setTitle("Mr");
c.setDob("1982-01-08");
c.setEmployeeId("2898373");
e.setCustomer(c);
given().spec(requestSpec).and().body(e).when().post("/api/v6/applications").then().assertThat()
Easiest ways to test :
String abc = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(e);
System.out.println(abc);
or
System.out.println(new Gson().toJson(e));

How to change object properties name when serialize?

I have an object like this.
public class Profile {
private String email;
private String phone;
#SerializedName("userCode")
private String user_code;
public String getEmail() {
return email;
}
public String getPhone() {
return phone;
}
public String getUser_code() {
return user_code;
}
}
This is what I got when I return that object in Rest API
{
"email": "abc#gmail.com",
"phone": 12345678,
"user_code": "742aeaefac"
}
Apparently annotation #SerializedName here did not work, I can understand that it get the object properties name base on its getter name, not in the annotation. If I change the getter name into getUserCode(), it will work as I expected.
I also try to use #JsonProperty but didn't help too.
Can someone explain what is the work here to solve this?
Update the code for serialization process in the controller.
#PostMapping(path = "/login", produces = "application/json")
#ResponseBody
public ClientRepresentation login(#RequestBody LoginRequest login) {
Map<String, Object> resObj = new HashMap<String, Object>();
ProfileResponse profileResponse = userService.findUserProfileByUserCode(login.getUserCode());
//Code logic to process object data...
resObj.put("profile", profileResponse);
return ClientRepresentationBuilder.buildClientRep(HttpStatus.OK.value(), "Success", resObj);
}
ClientRepresentation class
public class ClientRepresentation implements Serializable {
private Integer code;
private String message;
private Object data;
}

JSON deserialiser to set custom properties in POJO

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

Deserialize JSON array to a single Java object with Jackson

The idea is that I'd like to convert a JSON array ["foo", "bar"] into a Java object so I need to map each array element to property by index.
Suppose I have the following JSON:
{
"persons": [
[
"John",
"Doe"
],
[
"Jane",
"Doe"
]
]
}
As you can see each person is just an array where the first name is an element with index 0 and the last name is an element with index 1.
I would like to deserialize it to List<Person>.
I use mapper as follows:
mapper.getTypeFactory().constructCollectionType(List.class, Person.class)
where Person.class is:
public class Person {
public final String firstName;
public final String lastName;
#JsonCreator
public Person(#JsonProperty() String firstName, #JsonProperty String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
I was wondering if I can somehow specify array index as #JsonProperty argument instead of it's key name?
Thanks to bureaquete for suggestion to use custom Deserializer. But it was more suitable for me to register it with SimpleModule instead of #JsonDeserialize annotation. Below is complete JUnit test example:
#RunWith(JUnit4.class)
public class MapArrayToObjectTest {
private static ObjectMapper mapper;
#BeforeClass
public static void setUp() {
mapper = new ObjectMapper();
SimpleModule customModule = new SimpleModule("ExampleModule", new Version(0, 1, 0, null));
customModule.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(customModule);
}
#Test
public void wrapperDeserializationTest() throws IOException {
//language=JSON
final String inputJson = "{\"persons\": [[\"John\", \"Doe\"], [\"Jane\", \"Doe\"]]}";
PersonsListWrapper deserializedList = mapper.readValue(inputJson, PersonsListWrapper.class);
assertThat(deserializedList.persons.get(0).lastName, is(equalTo("Doe")));
assertThat(deserializedList.persons.get(1).firstName, is(equalTo("Jane")));
}
#Test
public void listDeserializationTest() throws IOException {
//language=JSON
final String inputJson = "[[\"John\", \"Doe\"], [\"Jane\", \"Doe\"]]";
List<Person> deserializedList = mapper.readValue(inputJson, mapper.getTypeFactory().constructCollectionType(List.class, Person.class));
assertThat(deserializedList.get(0).lastName, is(equalTo("Doe")));
assertThat(deserializedList.get(1).firstName, is(equalTo("Jane")));
}
}
class PersonsListWrapper {
public List<Person> persons;
}
class Person {
final String firstName;
final String lastName;
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
class PersonDeserializer extends JsonDeserializer<Person> {
#Override
public Person deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
JsonNode node = jp.readValueAsTree();
return new Person(node.get(0).getTextValue(), node.get(1).getTextValue());
}
}
Note that if you do not need wrapper object, you can deserialize JSON array
[["John", "Doe"], ["Jane", "Doe"]] directly to List<Person> using mapper as follows:
List<Person> deserializedList = mapper.readValue(inputJson, mapper.getTypeFactory().constructCollectionType(List.class, Person.class));
It is easy to serialize, but not so easy to deserialize in such manner;
The following class can be serialized into an array of strings as in your question with #JsonValue;
public class Person {
private String firstName;
private String lastName;
//getter,setter,constructors
#JsonValue
public List<String> craeteArr() {
return Arrays.asList(this.firstName, this.lastName);
}
}
But to deserialize, I had to create a wrapper class, and use custom deserialization with #JsonDeserialize;
public class PersonWrapper {
#JsonDeserialize(using = CustomDeserializer.class)
private List<Person> persons;
//getter,setter,constructors
}
and the custom deserializer itself;
public class CustomDeserializer extends JsonDeserializer<List<Person>> {
#Override
public List<Person> deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
JsonNode node = jsonParser.readValueAsTree();
ObjectMapper mapper = new ObjectMapper();
return IntStream.range(0, node.size()).boxed()
.map(i -> {
try {
List<String> values = mapper.readValue(node.get(i).toString(), List.class);
return new Person().setFirstName(values.get(0)).setLastName(values.get(1));
} catch (IOException e) {
throw new RuntimeException();
}
}).collect(Collectors.toList());
}
}
You need to put proper validation in deserializer logic to check that each mini-array contains exactly two values, but this works well.
I'd rather use these steps, and maybe to hide #JsonDeserialize, I'd do the following;
#Retention(RetentionPolicy.RUNTIME)
#JacksonAnnotationsInside
#JsonDeserialize(using = CustomDeserializer.class)
public #interface AcceptPersonAsArray {}
So you can use some custom annotation in PersonWrapper
public class PersonWrapper {
#AcceptPersonAsArray
private List<Person> persons;
//getter,setter,constructors
}

Object Mapper Values Returning Null

I'm using an Ajax Post request using jQuery to send data to Spring MVC. Two of those values are String data types while the other two are int. I get the following error: Can not instantiate variable of type.....From Integral number...
I'm receiving the data I sent from the client side into my server side Java code, but the values with the object mapper are null (i.e. personid = om.readValue(id, MyClass.class);) And those same lines are where the error points to. Changing Map<String,String> to be Map<String, Object> will not work either.
Below is my code. Any help would be greatly appreciated.
JSON:
{
id:"35",
firstname : "John",
lastname : "Doe",
age: "40"
}
Controller:
#RequestMapping(value="/mywebservice", method = RequestMethod.POST)
public Object getPerson(#RequestBody Map<String, String> mydata){
MyClass personid = null;
MyClass fname = null;
MyClass lname = null;
MyClass personage = null;
String id = "";
String firstname = "";
String lastname = "";
String age = "";
ObjectMapper om = new ObjectMapper();
if(mydata.containsKey("id"){
id = mydata.get("id");
}
if(mydata.containsKey("firstname"){
firstname = mydata.get("firstname");
}
if(mydata.containsKey("lastname"){
lastname = mydata.get("lastname");
}
if(mydata.containsKey("age"){
age = mydata.get("age");
}
try{
personid = om.readValue(id, MyClass.class);
fname = om.readValue(firstname, MyClass.class);
lname = om.readValue(lastname, MyClass.class);
personage = om.readValue(age, MyClass.class);
}catch(Exception e){ ...}
return helperClass(personid, fname, lname, personage);
}
Helper Class:
public Object getFirstName(MyClass personid, MyClass fname, MyClass lname, MyClass personage){
return addName(personid, fname, lname, personage);
}
Model:
#JsonProperty("id")
private int childid;
#JsonProperty("firstname")
private String firstname;
#JsonProperty("lastname")
private String lastname;
#JsonProperty("age")
private int childage;
Try change the json?
{
id:35,
firstname : "John",
lastname : "Doe",
age: 40
}

Categories