JSON Serialization and Deserialization

JSON Serialization

package com.json.demo9_5_21;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class JsonSerializeDemo {
	public static void main(String[] args) throws JsonProcessingException {
		ObjectMapper objectMapper = new ObjectMapper();
		Person person = new Person();
		person.setId(1);
		person.setName("Tyson");
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person));
	}
}

class PersonSerializer extends JsonSerializer<Person>{

	@Override
 	public void serialize(Person person, JsonGenerator  jsonGenerator, SerializerProvider serializerProvider)
			throws IOException, JsonProcessingException {
		jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
		jsonGenerator.writeStartObject();
		jsonGenerator.writeFieldName("custome serializer");
		jsonGenerator.writeString("Person Json");
		
		jsonGenerator.writeStringField("Person Json id","Persons Id : "+person.getId());
		jsonGenerator.writeStringField("Person Json Name","Persons Name : "+person.getName());
		
		jsonGenerator.writeEndObject();
	}	
}

@JsonSerialize(using = PersonSerializer.class)
class Person {
	int id;
	String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

JSON Deserialization

package com.json.demo10_5_22;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class JsonDeserializerDemo {
	public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
		ClassLoader classLoader = JsonDeserializerDemo.class.getClassLoader();
		ObjectMapper objectMapper = new ObjectMapper();
		Person person = objectMapper.readValue(new File(classLoader.getResource("person.json").getFile()),Person.class);
		System.out.println(person);
	}
}

class PersonDeserializer extends JsonDeserializer<Person>{

	@Override
	public Person deserialize(JsonParser jsonParser, DeserializationContext context)
			throws IOException, JsonProcessingException {
		ObjectCodec codec = jsonParser.getCodec();
		JsonNode root = codec.readTree(jsonParser);
		Person person = new Person();
		person.setId(Integer.valueOf(root.get("Person Json id").asText().replace("Persons Id : ","")));
		person.setName(root.get("Person Json Name").asText().replace("Persons Name :", ""));
		return person;
	}
	
}

@JsonDeserialize(using = PersonDeserializer.class)
class Person {
	int id;
	String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String toString() {
		return "Id : "+this.id+"\nName : "+this.name;
	}
}

JSON Tree Model

JSON Tree Model Reader

package com.json.demo7_4_2;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TreeModelReader {
	public static void main(String[] args) throws JsonProcessingException, IOException {
		ObjectMapper objectMapper = new ObjectMapper();
		ClassLoader classLoader = TreeModelReader .class.getClassLoader();
		JsonNode root = objectMapper.readTree(new File(classLoader.getResource("mapJson.json").getFile()));
		JsonNode key1 = root.get("key1");
		System.out.println("Key 1 : "+key1.asText());
		JsonNode array = root.get("Array");
		for(JsonNode x : array) {
			System.out.println(x.asText());
		}
	}
}

JSON Tree Model Writer

package com.json.demo8_4_3;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class TreeModelWrite {
	public static void main(String[] args) throws JsonProcessingException, IOException {
		ObjectMapper objectMapper = new ObjectMapper();
		ClassLoader classLoader = TreeModelWrite .class.getClassLoader();	
		JsonNode root = objectMapper.readTree(new File(classLoader.getResource("mapJson2.json").getFile()));
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root));
		//Removing key2
		((ObjectNode)root).remove("key2");
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root));
	}
}

JSON java jackson Annotations

package com.json.demo6_3_3;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.json.demo6_3_3.Person.BooksRead;
import com.json.demo6_3_3.Person.QUALIFICAION;

public class JsonAnnotationsDemo {
	public static void main(String[] args) throws JsonProcessingException {
		ObjectMapper objectMapper = new ObjectMapper();
		Person person = new Person(1,"Tyson",70,true);
		person.setQualification(QUALIFICAION.MCA);
		BooksRead manSearchMeaning = person.new BooksRead(111,"Mans Search for Meaning",300);
		person.getListOfBooksRead().add(manSearchMeaning);
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person));
	}
}

@JsonPropertyOrder({"id","name","age"})
@JsonInclude(JsonInclude.Include.NON_NULL) //removed justNull value from json
@JsonIgnoreProperties({"ownsCar"})
class Person {
	boolean ownsCar;
	@JsonProperty("Person ID ")
	int id;
	@JsonProperty("Person Age")
	int age;
	@JsonProperty("Person Name")
	String name;
	String justNull;
	List<BooksRead> listOfBooksRead = new ArrayList<>();
	QUALIFICAION qualification;
	@JsonIgnoreType //For Objects and enum and not for primitive data types
	enum QUALIFICAION { BCA,BSCIT,MCA,MSCIT,MS };
	
	Person(int id,String name,int age,boolean ownsCar){
		this.id = id;
		this.name = name;
		this.age = age;
		this.ownsCar = ownsCar;
	}
	
	class BooksRead{
		int bookId;
		String bookName;
		@JsonIgnore //Will not include bookPages in Json
		int bookPages;
		BooksRead(int bookId,String bookName,int bookPages){
			this.bookId = bookId;
			this.bookName = bookName;
			this.bookPages = bookPages;
		}
		public int getBookId() {
			return bookId;
		}
		public void setBookId(int bookId) {
			this.bookId = bookId;
		}
		public String getBookName() {
			return bookName;
		}
		public void setBookName(String bookName) {
			this.bookName = bookName;
		}
		public int getBookPages() {
			return bookPages;
		}
		public void setBookPages(int bookPages) {
			this.bookPages = bookPages;
		}
		
	}
	
	public String toString() {
		return "Id : "+id+" \nName : "+name+" \nAge : "+age;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isOwnsCar() {
		return ownsCar;
	}

	public void setOwnsCar(boolean ownsCar) {
		this.ownsCar = ownsCar;
	}

	public List<BooksRead> getListOfBooksRead() {
		return listOfBooksRead;
	}

	public void setListOfBooksRead(List<BooksRead> listOfBooksRead) {
		this.listOfBooksRead = listOfBooksRead;
	}

	public QUALIFICAION getQualification() {
		return qualification;
	}

	public void setQualification(QUALIFICAION qualification) {
		this.qualification = qualification;
	}

	public String getJustNull() {
		return justNull;
	}

	public void setJustNull(String justNull) {
		this.justNull = justNull;
	}
}

Read and Write JSON with File

Write JSON to file

package com.json.demo4_27;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class WriteJsonToFile {
	public static void main(String[] args) throws IOException {
		ObjectMapper objectMapper = new ObjectMapper();
		Map<String,Object> mapJson = new LinkedHashMap<>();
		mapJson.put("key1","value1");
		mapJson.put("key2","value2");
		mapJson.put("key3","value3");
		mapJson.put("booleanTrue",true);
		mapJson.put("booleanFalse",false);
		mapJson.put("Integer One",1);
		mapJson.put("Integer Two",2);
		mapJson.put("Object",new Person(1,"Tyson",60));
		mapJson.put("NullValue",null);
		mapJson.put("Array",new String[] {"One","Two","Three"});
		mapJson.put("ArrayOfObjects",new Person[] {new Person(1,"Tyson",60),new Person(2,"Justin",70)});
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapJson));
		//Writing the json to file
		objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File("map.json"),mapJson);
	}
}
class Person {
	@JsonProperty(value = "Person ID")
	int id;
	@JsonProperty(value = "Person Name")
	String name;
	@JsonProperty(value = "Person Age")
	int age;
	
	Person(int id,String name,int age){
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

Read JSON from File

package com.json.demo5_28;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DatabindJsonToObjectFromFile {
	public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
		String jsonFile = "/home/tyson/Documents/Application-Data/eclipse-workspace/Demo/lib/map.json";
		ObjectMapper objectMapper = new ObjectMapper();
		ClassLoader classLoader = DatabindJsonToObjectFromFile.class.getClassLoader();
		Map<String,Object> map = objectMapper.readValue(new File(classLoader.getResource("map.json").getFile()), 
				new TypeReference<Map<String,Object>>(){});
		System.out.println(map);
	}
}

JSON with Map, Object, Array, Array Of Object

package com.json.demo3_26;

import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MapToJson {
	public static void main(String[] args) throws JsonProcessingException {
		Map<String,Object> mapJson = new LinkedHashMap<>();
		mapJson.put("key1","value1");
		mapJson.put("key2","value2");
		mapJson.put("key3","value3");
		mapJson.put("booleanTrue",true);
		mapJson.put("booleanFalse",false);
		mapJson.put("Integer One",1);
		mapJson.put("Integer Two",2);
		mapJson.put("Object",new Person(1,"Tyson",60));
		mapJson.put("NullValue",null);
		mapJson.put("Array",new String[] {"One","Two","Three"});
		mapJson.put("ArrayOfObjects",new Person[] {new Person(1,"Tyson",60),new Person(2,"Justin",70)});
		System.out.println(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(mapJson));
	}
}
class Person {
	@JsonProperty(value = "Person ID")
	int id;
	@JsonProperty(value = "Person Name")
	String name;
	@JsonProperty(value = "Person Age")
	int age;
	
	Person(int id,String name,int age){
		this.id = id;
		this.name = name;
		this.age = age;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

JSON databinding with Jackson Annotations

package com.json.demo2_25;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Binding an Object to a JSON using Annotations
 * @author tyson
 *
 */
public class DataBindingWithAnnotations {
	public static void main(String[] args) throws JsonProcessingException {
		ObjectMapper objectMapper = new ObjectMapper();
		Person tyson = new Person();
		tyson.setAge(99);
		tyson.setId(1);
		tyson.setName("Tyson Gill");
//		System.out.println(objectMapper.writeValueAsString(tyson));
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(tyson));
	}
}
class Person {
	@JsonProperty(value = "Person ID")
	int id;
	@JsonProperty(value = "Person Name")
	String name;
	@JsonProperty(value = "Person Age")
	int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

JSON databinding in java

Converting java object to Json string

package com.json.demo1_24;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Binding an Object to a JSON without Annotations
 * @author tyson
 *
 */
public class DataBinding {
	public static void main(String[] args) throws JsonProcessingException {
		ObjectMapper objectMapper = new ObjectMapper();
		Person tyson = new Person();
		tyson.setAge(99);
		tyson.setId(1);
		tyson.setName("Tyson Gill");
//		System.out.println(objectMapper.writeValueAsString(tyson));
		System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(tyson));
	}
}
class Person {
	int id;
	String name;
	int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

Cloning in java

  • The process of creating exactly duplicate object is called Cloning.
  • The main purpose of cloning is to maintain backup copy and to preserve state of an object.
  • We can perform cloning by using clone method of object class.
  • clone() method is present in Object class
    Syntax :
    protected native Object clone() throws CloneNotSupportedException;
  • Note : The default cloning provided by object class’s method is called shallow cloning. i.e if we clone an object which contains a object in it then that object is not cloned instead the cloned object point to the same sub object.

Demo Program of Cloning :

package com.clonable.demo1;

public class ClonableDemo {
	public static void main(String[] args) throws CloneNotSupportedException {
		Demo demoObj1 = new Demo();
		demoObj1.setX(10);
		demoObj1.setY(20);
		Demo demoObj2 = demoObj1;
		System.out.println("Initial Object : "+demoObj1);
		demoObj2.setX(30);
		System.out.println("Value is changes due to use of reference : "+demoObj1);
		Demo demoObj3 = (Demo)demoObj1.clone();
		demoObj3.setX(3333);
		demoObj3.setY(3333);
		System.out.println("Value does not change due to use of clone : "+demoObj1);
		System.out.println("Printing Cloned Object : "+demoObj3);
	}
}
class Demo implements Cloneable {
	int x;
	int y;
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String toString(){
		return "X : " +x+ " Y : "+y;
	}
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
}

Points to remember while writing the above code :

  • clone() method is present in Object class and not in Cloneable Interface
  • clone() method is a protected method hence you may have to override the method to make it visible
  • clone() method returns an Object and we need to type cast it to our required method
  • Clonable Interface is a marker interface and it does not contain any methods.
  • Clonable Interface needs to be implemented to a class to call the clone() method on its object else may result into a runtime exception.

Shallow Cloning :

  • The process of creating bit wise copy of an object is called shallow cloning.
  • If the main object contain primitive variables then exactly duplicate copies will be created in the cloned object.
  • If the main object contain any reference variable then corresponding object wont be created just duplicate reference variable will be created pointing to old contained object
  • Object class clone method is meant for shallow cloning.
  • In shallow cloning by using cloned object reference if we perform any change to the contained object then those changes will be reflected to the main object.
  • To overcome this problem we should go for deep cloning.
  • If object contains only primitive variables then we should go for Shallow Cloning.
package com.cloneable.demo3;

public class DemoShallowCloning {
	public static void main(String[] args) throws CloneNotSupportedException {
		Person tyson = new Person(new Employee(1000),10);
		System.out.println("Tyson Object : "+tyson);
		Person justin = (Person)tyson.clone();
		justin.e.salary=2000;
		justin.age=12;
		System.out.println("Tyson Object's Salary changes even after clone since shallow clone : "+tyson);
	}
}
class Employee{
	public int salary;
	Employee(int salary){
		this.salary = salary;
	}
}
class Person implements Cloneable{
	public int age;
	public Employee e;
	Person(Employee e, int age){
		this.e = e;
		this.age = age;
	}
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	public String toString() {
		return "Salary : "+e.salary+" Age : "+age;
	}
}
Output

Deep Cloning :

  • The process of creating exactly duplicate independent copy including contained object is called deep cloning.
  • In deep cloning if the main object contain any primitive variables then in the cloned object duplicates copies will be created.
  • If the parent object contains any reference variable then the corresponding contained objects will be created in the cloned copy.
  • By default object class clone method meant for shallow cloning but we can implement deep cloning explicitly by overriding clone method in our class.
  • By using cloned object reference if we perform any change to the contained object then those changes won’t be reflected to the main object.
  • If object contains reference variables then we should go for deep cloning
package com.cloneable.demo2;

public class DemoShallowCloning {
	public static void main(String[] args) throws CloneNotSupportedException {
		Person tyson = new Person(new Employee(1000),10);
		System.out.println("Tyson Object : "+tyson);
		Person justin = (Person)tyson.clone();
		justin.e.salary=2000;
		justin.age=12;
		System.out.println("Tyson Object's Salary remains same after clone since deep cloning : "+tyson);
	}
}
class Employee{
	public int salary;
	Employee(int salary){
		this.salary = salary;
	}
}
class Person implements Cloneable{
	public int age;
	public Employee e;
	Person(Employee e, int age){
		this.e = e;
		this.age = age;
	}
	public Object clone() throws CloneNotSupportedException {
		return new Person(new Employee(this.e.salary),this.age);
	}
	public String toString() {
		return "Salary : "+e.salary+" Age : "+age;
	}
}
Output

NavigableMap Interface

  • NavigableMap is the child interface of SortedMap
  • NavigableMap provides several utility methods to navigate through the map
  • Implemention class of NavigableMap is TreeMap
  • NavigableMap was introduced in java 1.6 version

Implementation Class of NavigableMap interface

  • TreeMap

Features of NavigableMap :

  • When we need to store data in keyvalue map as well as in sorted order.
  • NavigableMap adds some utility methods to navigate through this sortedmap.