How to convert an object that has an inner object into JSON - java

I am having an object as below
public class Employee{
String firstName;
String lastName;
String address;
String phoneNumber;
List<Contacts> Contacts;
}
public class Contacts{
String name;
String Address;
String phoneNumber;
}
Now considering the Employee object is set with values inside the application and when I try to convert the object say with name empObject(which has all values) into JSON as below
ObjectMapper mapper= new ObjectMapper();
String employeeObjToJSON =mapper.writeValueAsString(empObject);
System.out.println("JSON employee Object" +employeeObjToJSON)
I get the values
{"firstName":"Sawyer","lastName":"Ford","phone":"4555454553", "address": "SNJFJJFJ", "contacts":[{"phoneNumber": "122333"},{"phoneNumber":"122222"}]}
Only the phone number is printed for the Inner Object. How should I get the complete object in JSON

Your class structure seems a little off. Why would the Employee class have a list of contacts as String, rather than a list of Contact objects?
I would suggest you change your Employee class like this:
public class Employee {
String firstName;
String lastName;
String address;
String phoneNumber;
List<Contact> contacts;
}
public class Contact {
String name;
String address;
String phoneNumber;
}
Using this class structure you should not have any problems mapping them to JSON using ObjectMapper.
Edit:
Regarding the null fields not being displayed, as I wrote in the comment, by default Jackson should serialise them and you should see them in the response.
If that is not the case, it might be that this serialisation feature has been overridden somewhere... try setting the following config to your object mapper and see if it works: mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS).
Alternatively, you can also use the Jackson annotation #JsonInclude(JsonInclude.Include.ALWAYS) on your Employee class and Contact class like ibenjelloun suggested in his/her answer.

Did you try the following class annotation :
#JsonInclude(JsonInclude.Include.ALWAYS)
According to the javadoc, it's the default value, maybe it is overwritten somewhere in your code ?

Related

Mapping multiple simple JSON fields to complex POJO with Jackson

I am trying to map a JSON structure to a specific POJO that doesn't really match the JSOM, here is a simple example:
JSON
{
"strA": "MyStr",
"Street": "1st Lane",
"Number": "123"
}
POJO
#JsonIgnoreProperties(ignoreUnknown = true)
public class ClassA {
#JsonProperty("strA")
private String strA;
private Address address;
//Constructor, getter,setter
#JsonRootName("Address")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Address {
private String address;
public Address() {
}
public String getAddress() {
return address;
}
#JsonAnySetter
public void setAddress(#JsonProperty("Street") String street, #JsonProperty("Number")String number) {
this.address = number + " " + street;
}
}
Now, Address is properly created from the sample JSON (only made it work with the JsonAnySetter unfortunately), but I can't get ClassA to be created properly.
I've tried annotating the Address property of it, but to no avail.
How can I achieve this in a "simple" way? This is important as this example is simple, but my real use cases involves several composed classes that need information from the JSON root + from complex JSON elements with different names.
Thank you for your time.

How to map single JSON field to multiple JAVA field with GSON?

I'm trying to parse JSON using Retrofit and Gson, but I need to map one JSONfield
's value to multiple JAVA fields inside bean class.
Here is an example code:
class A{
#SerializedName("name");
private String name;
#SerializedName("name");
private String fullName;
}
This is the error I'm seeing: class A declares multiple JSON fields named name. Is there any way to do this?
Update: Please avoid suggesting removing one field from the bean or making changes into getter and setter. The project is huge, and the field is being used later in many other cases, so I don't want to mess with the structure. The question is pretty much clear and on the point.
No need to declare JSON for fullname use name value with fullname in setter gatter.
class A{
#SerializedName("name");
private String name;
private String fullName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFullName() {
return name;
}
public void setFullName(String fullName) {
this.name = fullName;
}
}

Boon JSON - Change Field Name for Object Deserialization

I am using Boon JSON and I'd like to change the name of a field on a class that is being generated from JSON.
I just want to change
{"first_name": "Cristine", "last_name": "McVie"}
So it maps to the Java fields:
String firstName;
String lastName;
I've already got everything working (ie, if I use camel-case in the JSON, the object is created properly.
I've tried the #JsonPropery and (based on the suggestion in comments) the #Named annotations on the class, like so:
public class Person {
#Named("first_name")
private String firstName;
#Named("first_name")
public String getFirstName() {
return firstName;
}
#Named("first_name")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
Just for edification, this is why I didn't see #JsonProperty working at first. This app is running in Eclipse debug mode, and I was trusting Eclipse to redeploy the updated code, but adding an annotation is apparently NOT enough to trigger the update. Had to restart the app to pick it up.
You need to add either a SerializedName annotation (like GSON) or aJsonProperty annotation (like Jackson) to the fields, like so:
import org.boon.json.annotations.JsonProperty;
import org.boon.json.annotations.SerializedName;
public static class Person {
#SerializedName("first_name")
String firstName;
#JsonProperty("last_name")
String lastName;
}
You can see another example in the documentation.

How to dynamically build a class in java

All:
I am pretty new in Java. What I want to do is build a java data model object dynamically according to the CSV fields it reads in, like:
file1.csv
Name, Age, Email, Url
Allen, 30, allen#mail.com, http://allen.mail.com
Bob, 20, bob#mail.com, http://bob.mail.com
Firstly I read in the header, and according to the header, I want to create a class InfoModel which has those field names as its member variable.
Could anyone help? Thanks.
You could create the sourcecode dynamically, compile and load the class using the java API. But it would be pretty complicated to use the resulting class. You should simply use a hashmap for the variables in InfoModel and create the class before runtime. Would be simpler to use and more efficient.
You can create a corresponding Bean Class having Name, Age, Email, Url as member variable
Class Employee{
private String name;
private String age;
private String email;
private String url;
public Employee(String name,String age,String email,String url){
this.name=name;
this.age=age;
//and so on
}
// their getters and setters
}
// their getters and setters
}
Now as soon as you read the CSV lines after header , you can create Object of Employee Class
new Employee(name,age,email,url);
What I want to do is build a java data model object dynamically according to the CSV fields it reads in.
Ok, let's look at the CSV input again.
Name, Age, Email, Url
Allen, 30, allen#mail.com, http://allen.mail.com
Bob, 20, bob#mail.com, http://bob.mail.com
Here's the class that you want to generate.
package com.ggl.testing;
public class InfoModel {
private final String name;
private final int age;
private final String email;
private final String url;
public InfoModel(String name, int age, String email, String url) {
this.name = name;
this.age = age;
this.email = email;
this.url = url;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getEmail() {
return email;
}
public String getUrl() {
return url;
}
}
So, here is the main question you have to answer to generate the text of this class from the CSV file.
How do I determine what type of data is in the CSV file? In other words, how do I determine that Age is an int? How do I determine that Name is a String?
Once you've figured out the data types, you can output the text of the InfoModel class by using a lot of StringBuilders.
See my article, Writing Java Code that Writes Java Code, for an example of how to write a Java application that writes Java classes.
Just an idea... If the fields are limited, for example if you only need various combinations of fields, you could create an interface for each field (getter and setter) and then creaty a Proxy object for all of them, handling the data, for example, with an internal HashMap. This will get you an object that implements all of the interfaces, but of course, only in a very specific way.

Strategy for using Morphia to persist domain objects without adding unnecessary annotations to domain objects?

Hypothetically, lets say I have a domain object called Person. It looks like such:
public class Member {
private final String firstName;
private final String lastName;
private final String email;
private final String password;
public Member(String firstName, String lastName, String email, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
}
I also have a MemberRepository interface that defines basic CRUD and some other sugary methods.
Now lets say I want to persist this domain object in a MongoDB instance using Morphia. I've created my MorphiaMemberRepository implementation but what I'm unsure of is how to store the domain object with as little mess as possible.
Any Morphia users would know that I'd need to create an ID field of type ObjectId and annotate it with #Id. Additionally I'd need to annotate the class with #Entity("members"). I don't necessarily want to clutter up my nice domain object with the Morphia/MongoDB specific annotations.
So...fellow stackers, what should I do to keep this implementation as clean as possible?
That is the requirement for Morphia (at least the #Id one). Annotations do not require changing the way you use your object or serialization. They are just extra metadata which most programs ignore; they are harmless.
If you have a unique field then you don't need to add any new ones, just mark that with #Id and be done with it.
If you really don't want to do any of this, you can manually create the metadata in morphia to deal with your classes, but that will be much more work as that process is not exposed via any external configuration format.
Suppose there is IMember so Member implements IMember. Getter methods are defined in IMember.
Another class MorphiaMember implements IMember is annotated as necessary and has ID field (id is not always ObjectId).
Each class has a factory method
public static Member from(IMember mi) { ... }
so typical workflow will be:
MemberRepository repo = ...
Member m = Member.from(repo.get(some_id))
...
Member m2 = ...
repo.save(MorphiaMember.from(m))

Categories

Resources