-
Notifications
You must be signed in to change notification settings - Fork 8
Serialization
SimpleJSON supports serialization and deserialization for JSON objects.
In order to use this functionality you first have to annotate the classes you want to serialize using the JSONRoot and JSONAttribute annotations. JSONRoot is applied on class level and marks the class as a JSON object. JSONAttribute can be applied to public fields and methods. It has 3 parameters. name is a required parameter and defines the key for the attribute. type is an array which defines if the attribute can read, written or both. And genericType should be applied on maps and lists to define the generic type of the value. In case of maps the type of the key will always be interpreted as a string.
Important things to note
- A class that was marked with
JSONRootmust have a public constructor without parameters otherwise the instantiation through Reflection will fail. - Attributes with the
transientmodifier will not be serialized. - Attributes whose type is an interface can be serialized but not deserialized since Reflection cannot create instances of interfaces. Because of that it is recommended to instead use implementations of these interfaces. Instead of
ListandMapuseArrayListandHashMap - Character arrays can be serialized but not deserialized. This is because upon serialization the character array will become a string array
- It is not necessary to implement the
Serializableinterface. - The parameter
genericTypeofJSONAttributeshould always be set when handling collections and maps. - The parameter
nameofJSONAttributeshould always be unique.
@JSONRoot
public class Person {
@JSONAttribute(name = "first_name")
public String firstName;
@JSONAttribute(name = "last_name")
public String lastName;
@JSONAttribute(name = "age")
public int age;
@JSONAttribute(name = "city")
public String city;
@JSONAttribute(name = "country")
public String country;
@JSONAttribute(name = "friends", genericType = Person.class)
public ArrayList<Person> friends;
}@JSONRoot
public class Person {
private String firstName;
private String lastName;
private int age;
private String city;
private String country;
private ArrayList<Person> friends;
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "first_name")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "last_name")
public void setLastName(String lastName) {
this.lastName = lastName;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "age")
public void setAge(int age) {
this.age = age;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "city")
public void setCity(String city) {
this.city = city;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "country")
public void setCountry(String country) {
this.country = country;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "friends", genericType = Person.class)
public void setFriends(ArrayList<Person> friends) {
this.friends = friends;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "first_name")
public String getFirstName() {
return this.firstName;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "last_name")
public String getLastName() {
return this.lastName;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "age")
public int getAge() {
return this.age;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "city")
public String getCity() {
return this.city;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "country")
public String getCountry() {
return this.country;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "friends")
// It is OK to only use List here since GETTER is only relevant for serialization
// and will have no relevance for deserialization
public List<Person> getFriends() {
return this.friends;
}
}A simple call of JSONSerializer#serialize or JSONSerializer#deserialize is all it takes.
Person person = new Person();
person.setFirstName("John");
person.setLastName("Doe");
person.setAge(21);
person.setCity("Example City");
person.setCountry("Example Country");
person.setFriends(johnDoesFriends);
try {
JSONObject jsonDOM = JSONSerializer.serialize(person);
System.out.println(jsonDOM);
} catch(Exception exception) {
exception.printStackTrace();
}try {
Person person = new Person();
JSONSerializer.deserialize(person, jsonDOM);
System.out.println(person.getFirstName());
System.out.println(person.getLastName());
System.out.println(person.getAge());
System.out.println(person.getCity());
System.out.println(person.getCountry());
System.out.println(person.getFriends());
} catch(Exception exception) {
exception.printSTackTrace();
}A non-JSON type is every type that is not a primitive, collection or map. Normally these values are treated as strings by calling their toString method but that may not always be wanted. An example of such a case would be dates and times. In order to properly handle such cases your class has to implement JSONTypeSerializationHandler.
In this example we will add a birth date to person.
@JSONRoot
public class Person implements JSONTypeSerializationHandler {
private String firstName;
private String lastName;
private int age;
private String city;
private String country;
private ArrayList<Person> friends;
private LocalDate birthDate;
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "first_name")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "last_name")
public void setLastName(String lastName) {
this.lastName = lastName;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "age")
public void setAge(int age) {
this.age = age;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "city")
public void setCity(String city) {
this.city = city;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "country")
public void setCountry(String country) {
this.country = country;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "friends", genericType = Person.class)
public void setFriends(ArrayList<Person> friends) {
this.friends = friends;
}
@JSONAttribute(type = JSONAttribute.Type.SETTER, name = "birth_date")
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "first_name")
public String getFirstName() {
return this.firstName;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "last_name")
public String getLastName() {
return this.lastName;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "age")
public int getAge() {
return this.age;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "city")
public String getCity() {
return this.city;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "country")
public String getCountry() {
return this.country;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "friends")
// It is OK to only use List here since GETTER is only relevant for serialization
// and will have no relevance for deserialization
public List<Person> getFriends() {
return this.friends;
}
@JSONAttribute(type = JSONAttribute.Type.GETTER, name = "birth_date")
public LocalDate getBirthDate() {
return this.birthDate;
}
@Override
public Object serialize(Class<?> type, Object value) {
if(LocalDate.class.equals(type) && value != null) {
return value.toString();
}
return value;
}
@Override
public Object deserialize(Class<?> type, Object value) {
if(LocalDate.class.equals(type) && value != null) {
return LocalDate.parse(value.toString());
}
return value;
}
}