How to Read CSV File in Java

Reading a CSV file in Java including handling BOM (Byte-Order-Marker), quoted fields, multi-line fields and more.

“The reason I talk to myself is because I’m the only one whose answers I accept.”
― George Carlin

1. Introduction

CSV files are extensively used in data interchange between applications. Especially useful when the only structure to the data being exchanged is rows and columns. This format is particularly popular as the data can be imported into Microsoft Excel and used for charts and visualization.

Continue reading “How to Read CSV File in Java”

Load XML into Mysql Using Java

Load XML into MySQL by using Java DOM Parser.

“Never memorize something that you can look up.”
― Albert Einstein

1. Introduction

XML provides the ability to represent hierarchical structure with its parent-child relationships. This enables applications to store structured data in XML for export. Importing this XML data into a database is a bit involved as we shall see in this article. You need to write code to manage the database connection. In addition you need parse the XML and isolate the data that needs to be imported.

Continue reading “Load XML into Mysql Using Java”

Java ArrayList Examples

1. Introduction

The ArrayList in Java is one of the most used classes in the JDK. It is an implementation of a resizable array with a range of useful methods for manipulating the array. In this article, we present some of the usage patterns of the ArrayList.

The ArrayList is a concrete implementation of the List interface. As such, it is fine to refer to List instead of ArrayList when the implementation detail does not matter. The examples below use List instead of ArrayList when this difference is not relevant.

2. Array vs ArrayList

A regular array in java is a container which holds a fixed number of elements of a specific type. The following (stringArray) is a declaration of an array of String objects and is initialized to an array enough to store 20 strings.

String[] stringArray = new String[20];

An ArrayList for storing Strings is defined as shown below. The number 20 is an indication to the ArrayList class to reserve enough space for 20 strings.

ArrayList<String> stringList = new ArrayList<String>(20);

Some of the differences between the two:

  • Addition: The stringArray can store upto 20 strings. If you need to store more later on, you will have to re-initialize the array and copy the contents from the old array. With the ArrayList, you can add more than 20 strings without worrying about the capacity.
  • Removal: With the ArrayList it is easy to remove entries, either at a particular index or a range or a particular object. Not so easy with the array. You will need loops and other boiler-plate code to manage the removal in your code.

3. Creating an ArrayList

As already shown above you can create an ArrayList using the constructor. To create an empty ArrayList with a capacity for 10 Objects:

ArrayList<Object> objArray = new ArrayList<>();

To create an ArrayList from another Collection such as a Set or a List, you can use:

Set<String> stringSet = ..;
List<String> list = new ArrayList<String>(stringSet);

What if you need to create a List from a bunch of objects already lying around in your code? You can use Arrays.asList() as follows:

List<String> list = Arrays.asList("Apple", "Banana", "Orange");

The following selects lines from a text file using Java 8 streams.

List<String> lines = Files
    .lines(Paths.get(textFile))
    .filter(x -> x.length() > 50)
    .collect(Collectors.toList());

4. Convert Array to ArrayList

As presented above, it is simple to convert to a List if you have a plain array of objects.

List<String> a = Arrays.asList(args);

The above is suitable if you have an array of objects. What if you have an array of a primitive type, say an int? Here is how you can handle that case.

int[] array = { 2, 4, 5 };
List<Integer> list = Arrays
    .stream(array)
    .boxed()
    .collect(Collectors.toList());

5. Convert ArrayList to Array

The List interface provides a method toArray() which creates and returns a new array containing all the elements in the ArrayList.

List<String> strList = ...;
String[] strArray = strList.toArray();

6. Add to ArrayList

Use the method add() to add items to a List. This invocation adds elements at the end of the list.

List<String> strList = new ArrayList<>();
strList.add("Apple");
strList.add("Banana");
strList.add("Orange");
strList.stream().forEach(System.out::println);

// prints
Apple
Banana
Orange

To add all elements of a collection, use addAll().

List<String> modList = new ArrayList<>();
modList.addAll(strList);
modList.add("Melon");

7. UnsupportedOperationException

The following code results in an UnsupportedOperationException. The reason is than Arrays.asList() returns a fixed sized list backed by the input array. So you cannot add elements to the List returned by Arrays.asList().

A simple solution is to create a new ArrayList from the original list as follows:

List<String> strList = Arrays.asList("Apple", "Banana", "Orange");
List<String> modList = new ArrayList<>(strList);
modList.add("Melon");

Or you could use Java 8 streams:

List<String> modList = strList
	.stream()
	.collect(Collectors.toList());
modList.add("Melon");
modList.stream().forEach(System.out::println);

// prints:
Apple
Banana
Orange
Melon

8. Remove from ArrayList

Removal of items from a List is also easy. Remove an element at a particular index.

List<String> modList = new ArrayList<>();
modList.addAll(strList);
modList.add("Melon");
modList.remove(2);

// contains:
Apple
Banana
Melon

Remove a particular object as shown below. Note: The equals() method is used for checking whether to remove the object. It works as shown for String. For another class, equals() might be defined in terms of memory addresses, in which case the same object instance must be passed in to remove it.

List<String> modList = new ArrayList<>();
modList.addAll(strList);
modList.add("Melon");
modList.remove("Orange");

// contains
Apple
Banana
Melon

What if you want to remove an object with some specific characteristic. Use the removeIf() method with the predicate. The methods removes all elements that match the predicate.

List<String> modList = new ArrayList<>();
modList.addAll(strList);
modList.add("Melon");
modList.removeIf(x -> x.endsWith("e"));

// contains
Banana
Melon

Remove all objects from one List that are found in another List using removeAll().

List<String> modList = new ArrayList<>();
modList.addAll(strList);
modList.add("Melon");
modList.removeAll(Arrays.asList("Banana", "Kiwi"));

// contains
Apple
Orange
Melon

Summary

This article explained Java arrays and ArrayList from the perspective of a beginner. We showed creation and initialization of ArrayList. The ArrayList provides a bunch of methods to add and remove elements from the list. In some cases, the List created may not be modifiable in which case an exception is thrown when you try to modify it.

Java File Examples

1. Introduction

Java provides the File class as an abstraction of file and directory path names. A path is presented as a hierarchical operating system independent view of files.

The File class supports a bunch of operations on files and directories which work on both Unix-like and Windows systems. Let us look at some of these operations in more detail.

2. Creating a New File

To create a new file, use the method createNewFile(). The following creates a new file “joe” in the current directory.

File file = new File("joe");
if ( file.createNewFile() ) System.out.println("created");

If a file specified already exists, the method returns false. In this case, the existing file is not touched or modified.

2.1. Hierarchy Not Created

The method does not automatically create the directory hierarchy if any of the parent directories do not exist. The following throws an exception if directory “joe” does not exist in the current directory.

File file = new File("joe/jack");
if ( file.createNewFile() ) System.out.println("created.");

// throws: java.io.IOException: Not a directory

However, if you run the above code after creating the parent directory, it works normally.

2.2. Creating Absolute Path File

In addition to specifying relative paths as above, you can also specify an absolute path as shown below:

File file = new File("/tmp/joe");
if ( file.createNewFile() ) System.out.println("created.");

// prints "created."

2.3. Permission Denied

When attempting to create a file where you don’t have permission, you get an exception:

File file = new File("/joe");
if ( file.createNewFile() ) System.out.println("created.");

// throws java.io.IOException: Permission denied

3. Delete a File

The File class provides a delete() method to delete a file. It is used as follows:

File file = new File("joe");
if ( file.delete() ) System.out.println("deleted.");

The method does not throw an exception if the file does not exists. It just returns false.

4. List Files

When a File object is created with a directory, you can use the list() method to list the files and directories in that directory. Here is an example of listing the files in the current directory using Java 8 streams.

Arrays.stream(file.list()).forEach(System.out::println);

You can also specify a FilenameFilter to select the required files. FilenameFilter is a functional interface so let us use a lambda expression to select and print the “.class” in the directory.

File file = new File(dirPath);
Arrays
    .stream(file.list((d, f) -> f.endsWith(".class")))
    .forEach(System.out::println);

In the above example, we use the FilenameFilter for filtering files by name. However, FileFilter is another functional interface provided by java that can be used to select files by some file property. In the following example, we select empty files.

File file = new File(path);
File[] emptyFiles = Arrays
    .stream(file.listFiles(f -> f.length() == 0));

Or select hidden files for processing.

File file = new File(path);
List<File> hiddenFiles = Arrays
    .stream(file.listFiles(f -> f.isHidden()))
    .collect(Collectors.toList());

5. Creating a Directory

The File class provides the method mkdir() to create a directory. It returns false if the directory cannot be created which could be for a variety of reasons. In other words, exceptions are not thrown including for the following reasons:

  • File or directory already exists.
  • No permission.
  • Hierarchy does not exist.
File file = new File(path);
if ( file.mkdir() ) System.out.println("created.");

If you want to create all non-existent directories of the hierarchy, use mkdirs() instead.

6. Renaming a File

To rename a file, use renameTo(). You must pass in a target File object to rename the file to.

File source = new File(pathA);
File target = new File(pathB);
if ( source.renameTo(target) ) System.out.println("renamed.");

Note that this method comes with a bunch of caveats including:

  • Might not be able to move a file from one file system to another.
  • Might not work if the target path exists. (In other words, might not overwrite the target file.)
  • It might not be atomic. In other words, removing the old file and creating the new file are two separate operations in which one might fail!

With all these warnings, it is better to check the return value to be sure the operation succeeded.

Summary

The Java File class is an system independent abstraction of file and directory paths. It provides a bunch of operations to create a file, remove a file, create a directory including the hierarchy and renaming files.

Java Enum Examples

1. Introduction

Java has provided native enum types from version 1.5 onwards. Some issues arise with the use of enums in java code which this article attempts to address.

2. Enum Abstract Method

An enum type can have abstract methods just like a class. Each enum constant needs to implement the abstract method. An example follows:

public enum Animal {
  Dog { String sound() { return "bark"; } },
  Cat { String sound() { return "meow"; } },
  Lion { String sound() { return "roar"; } },
  Snake { String sound() { return "hiss"; } };

  abstract String sound();
};

Use it as follows:

String str = "Dog";
Animal animal = Animal.valueOf(Animal.class, str);
System.out.println(animal + " makes sound: " + animal.sound());

// prints
Dog makes sound: bark

3. String to Enum

Use valueOf() to lookup an enum by the name.

private enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY 
};
Day day = Day.valueOf(Day.class, "MONDAY");

The method throws an IllegalArgumentException if the name (with the exact case) is not found.

Day day = Day.valueOf(Day.class, "Monday");

// throws an IllegalArgumentException

4. String to Enum Ignore Case

To lookup an enum by string ignoring the case, you can add a static method to the enum class and use it as shown.

static public Day forNameIgnoreCase(String value) {
    for (Day day : Day.values()) {
	if ( day.name().equalsIgnoreCase(value) ) return day;
    }
    return null;
}

No exceptions are thrown by this code.

String args[] = { "joe", "monday", "Monday", "MONDAY" };
for (String arg : args) {
    Day day = Day.forNameIgnoreCase(arg);
    System.out.println(arg + " => " + day);
}

// prints:
joe => null
monday => MONDAY
Monday => MONDAY
MONDAY => MONDAY

5. EnumSet – Set of Enums

Java also provides a new type EnumSet which is a Set of Enums and provides a bunch of useful operations.

Select a range of enums using EnumSet.range(). Enum constants are returned in the order of declaration.

for (Animal animal : EnumSet.range(Animal.Cat, Animal.Snake)) {
    System.out.println(animal);
}

The EnumSet can also be used as a type-safe alternative to traditional bit flags.

EnumSet.of(Style.BOLD, Style.ITALIC)

You can also add to the set using the normal Set.add() operation. Note that the order of looping is the declared order (and not the add order).

EnumSet<Animal> set = EnumSet.of(Animal.Cat);
set.add(Animal.Dog);
for (Animal animal : set) {
    System.out.println(animal);
}

// prints
Dog
Cat

Remove also works in a similar way. In the following example, we are adding all the enum constants to the set using EnumSet.allOf().

EnumSet<Animal> set = EnumSet.allOf(Animal.class);
set.remove(Animal.Snake);
for (Animal animal : set) {
 System.out.println(animal);
}

// prints
Dog
Cat
Lion

6. EnumMap – Enum as a Key

EnumMap is a specialized implementation of Map provided for cases where an enum is used as the key. According to the javadocs, the storage is compact and efficient. It is used similar to the way regular Maps are used with some change in construction; the enum class must be passed in to the constructor.

EnumMap<Animal,String> sounds = new EnumMap<Animal,String>(Animal.class);
sounds.put(Animal.Dog, "Bark");
sounds.put(Animal.Cat, "Meow");
for (Map.Entry<Animal,String> e : sounds.entrySet()) {
    System.out.println(e.getKey() + " => " + e.getValue());
}

// prints:
Dog => Bark
Cat => Meow

7. Enum Name Map

The implementation of the values() method creates an array every time it is invoked. To avoid invoking this method too many times, you can create a name map and use it for lookup. (Yes, that might possibly count as “premature optimization” but hopefully you are resorting to this approach only when invoking values() multiple times.)

static private enum Period {
    Day, Week, Fortnight, Month, Year;

    private static final Map<String,Period> nameMap = new HashMap<>();
    static {
	for (Period period : Period.values())
	    nameMap.put(period.name(), period);
    };

    static public Period forName(String value)
    {
	return nameMap.get(value);
    }
};

And use it like this. Note again that looking up a non-existent name does not result in an IllegalArgumentException.

String[] args = { "joe", "Day", "Week" };
for (String arg : args) {
    Period period = Period.forName(arg);
    System.out.println(arg + " => " + period);
}

// prints:
joe => null
Day => Day
Week => Week

8. Comparing Enums: == or equals()?

When comparing enum instances, what should you use?

Day day = ...;
if ( day == Day.MONDAY ) {
  // code here
}

if ( day.equals(Day.MONDAY) ) {
  // code here
}

Both are correct. In fact, equals() is implemented using ==. Since == never throws a NullPointerException, one might prefer using that.

9. Should I Use Enum Ordinals?

Enum ordinal is the index of the enum in the list returned by values().

Day[] days = Day.values();
for (int i = 0 ; i < days.length ; i++ ) {
    System.out.println(i + " => " + days[i]);
}

// prints:
0 => SUNDAY
1 => MONDAY
2 => TUESDAY
3 => WEDNESDAY
4 => THURSDAY
5 => FRIDAY
6 => SATURDAY

Sometimes you may want to store or transmit the ordinal as a part of storing the state. Should you use the ordinal in such cases? For instance:

System.out.println("4 => " + days[4]);

// prints
4 => THURSDAY

The answer is no, it is not a good idea to store or use the ordinal. It is a much better idea to store and transmit the name. Since the values() method returns the array in the order of declaration, using the ordinal might return wrong values if the enum definition is modified to add or remove entries.

Store and use the name. If the enum entry is removed later, valueOf() will throw an exception. Which is much better than using wrong values and not knowing about it.

Summary

We have now learnt some basics about enums in java. Enums in java are more powerful than in most other languages. Abstract methods can be declared for the enum and specialized implementation can be defined for each enum constant. Looking up enum constants in a case-insensitive operation is another area arising frequently.

Java NIO – Using ByteBuffer

1. Introduction

Java provides a class ByteBuffer which is an abstraction of a buffer storing bytes. While just a little bit more involved than using plain byte[] arrays, it is touted as more performant. in this article, let us examine some uses of ByteBuffer and friends.

Continue reading “Java NIO – Using ByteBuffer”

Apache POI Excel Example

Learn how to create an Excel spreadsheet from within Java using Apache POI, a library for working with Microsoft Documents.

1. Introduction

Apache POI is a Java library to read and write Microsoft Documents including Word and Excel. Java Excel API can read and write Excel 97-2003 XLS files and also Excel 2007+ XLSX files. In this article, we show how to get going using the Apache POI library to work with Excel files.

Continue reading “Apache POI Excel Example”

Jackson Tree Model

1. Introduction

Jackson represents the JSON object model as a tree of JsonNode objects. This is called the Tree Model since it comprises of a tree of JsonNodes, including ObjectNode and ArrayNode. The tree mirrors the structure of the JSON document. It can be created by parsing a JSON document or by creating an in-memory representation.

2. Parsing a JSON File

A JSON file can be parsed and a tree model representation can be created using the ObjectMapper.readTree().

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(new File(args[0]));

The resulting tree model can be converted back to a JSON document as follows:

System.out.println(mapper.writeValueAsString(root));

3. Convert a Java Object (POJO) to JsonNode

Let us learn how to build a tree model from a POJO (Plain Old Java Object). Consider these classes:

public class Address {
    private String address1;
    private String address2;
    private String city;
    private String state;
    private String zip;
}

public class User
{
    private String firstName;
    private String lastName;
    private Address address;
}

Instantiate the objects as required:

User user = new User();
user.setFirstName("Harrison");
user.setLastName("Ford");
Address address = new Address();
address.setAddress1("123 Main Street");
address.setCity("Hollywood");
address.setState("CA");
address.setZip("33023");
user.setAddress(address);

A single function call suffices to convert the POJO to a JsonNode.

JsonNode root = mapper.valueToTree(user);
System.out.println(mapper.writeValueAsString(root));

The output JSON is:

{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address" : {
    "address1" : "123 Main Street",
    "address2" : null,
    "city" : "Hollywood",
    "state" : "CA",
    "zip" : "33023"
  }
}

4. Convert a JsonNode to POJO

Once you have assembled a tree model from the JsonNode instances, how can you convert it to a POJO? Quite easy and all the contained JsonNode instances are also converted properly.

User user = mapper.treeToValue(root, User.class);

5. Convert Generic Containers to JsonNode

You can build up an object representation from nothing more than Java’s generic containers such as Map and List. Is it possible to convert such a representation to a tree model (JsonNode)? Of course it is. Use ObjectMapper.valueToTree() as before.

Map<String, Object> user = new HashMap<>();
user.put("firstName", "Harrison");
user.put("lastName", "Ford");
user.put("emailAddress", Arrays.asList("harrison@example.com",
              "hford@actors.com"));

Map<String, Object> addr = new HashMap<>();
addr.put("address1", "123 Main Street");
addr.put("address2", null);
addr.put("city", "Hollywood");
addr.put("state", "CA");
addr.put("zip", "33023");
user.put("address", addr);

JsonNode root = mapper.valueToTree(user);
System.out.println(mapper.writeValueAsString(root));

// prints:
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "emailAddress" : [ "harrison@example.com", "hford@actors.com" ],
  "address" : {
    "zip" : "33023",
    "address2" : null,
    "city" : "Hollywood",
    "address1" : "123 Main Street",
    "state" : "CA"
  }
}

And of course, once you have the JsonNode tree model, you can use Jackson data binding to create a Java object (POJO).

User userAgain = mapper.treeToValue(root, User.class);

6. Iterating over a JsonNode

Once you have a JsonNode, how can you find out what it contains? You can loop over its contents and extract the children.

Find the key names of a JsonNode (assuming it is an ObjectNode). And lookup the value JsonNode using JsonNode.get(String).

JsonNode parent = ...;
for (Iterator<String> it = parent.fieldNames() ; it.hasNext() ; ) {
    String field = it.next();
    System.out.println(field + " => " + parent.get(field));
}

Or iterate over the fields, again assuming it is an ObjectNode:

for (Iterator<Map.Entry<String,JsonNode>> it = parent.fields() ;
     it.hasNext() ; ) {
    Map.Entry<String,JsonNode> e = it.next();
    System.out.println(e.getKey() + " => " + e.getValue());
}

Fetch and iterate over all the elements. This one works with an ArrayNode too.

for (Iterator<JsonNode> it = parent.elements() ; it.hasNext() ; ) {
    JsonNode node = it.next();
    System.out.println(node);
}

7. Creating a Tree Model from Scratch

You can also completely generate a tree model from scratch. Start by creating an ObjectNode and populate it using JsonNode.with(). Here we create the above User instance with the associated Address as shown below.

ObjectNode root = mapper.createObjectNode();
root.put("firstName", "Harrison");
root.put("lastName", "Ford");
root.with("address").put("address1", "123 Main Street");
root.with("address").put("address2", null);
root.with("address").put("city", "Hollywood");
root.with("address").put("state", "CA");
root.with("address").put("zip", "33023");
System.out.println(mapper.writeValueAsString(root));

8. Adding Items to a List

For adding lists into the JSON tree model, you can start with the method withArray() and add items as shown:

root.withArray("Genre").add("Drama").add("Horror");

// results in:
{
 ..
 "Genre" : [ "Drama", "Horror" ],
 ..
}

9. Adding from a List

Here is an example of using Java 8 Streams to add nodes from a List:

Arrays.asList("Stephen King (novel)",
                 "Stanley Kubrick (screenplay)",
                 "Diane Johnson (screenplay)")
    .stream()
    .forEach(root.withArray("Writer")::add);

// looks like:
{
 ..
 "Writer" : [ "Stephen King (novel)", "Stanley Kubrick (screenplay)", "Diane Johnson (screenplay)" ]
 ..
}

10. Adding from a Map

And adding to a tree model from a Map is similarly easy:

map.put("cat", "meow");
map.put("dog", "bark");
map.put("cow", "moo");
map
    .entrySet()
    .stream()
    .forEach(e -> root.with("animals").put(e.getKey(), e.getValue()));

// output:
{
 "animals" : {
   "cat" : "meow",
   "cow" : "moo",
   "dog" : "bark"
 }
}

11. Using JsonPointer

JsonPointer is a proposed standard for addressing nodes within a JSON document (somewhat similar to XPath for XML documents). Jackson supports extraction of JsonNodes with a JsonPointer expression using the method JsonNode.at().

JsonNode root = mapper.readTree(new File(jsonFile));
String jsonPtr = ...;
System.out.println(mapper.writeValueAsString(root.at(jsonPtr)));

Let us see some examples of JsonPointer. Consider this JSON.

{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "emailAddress" : [ "harrison@example.com", "hford@actors.com" ],
  "address" : {
    "zip" : "33023",
    "address2" : null,
    "city" : "Hollywood",
    "address1" : "123 Main Street",
    "state" : "CA"
  }
}

Here are some examples of JsonPointer expression evaluation on this document.

/firstName: "Harrison"

/emailAddress: [ "harrison@example.com", "hford@actors.com" ]

/emailAddress/0: "harrison@example.com"

/emailAddress/1: "hford@actors.com"

/address: {
  "zip" : "33023",
  "address2" : null,
  "city" : "Hollywood",
  "address1" : "123 Main Street",
  "state" : "CA"
}

/address/zip: "33023"

Summary

This article demonstrated how to easily work with the tree model in JSON. We showed how to parse JSON into JsonNode and also how to extract information from the tree model.

Guide to Jackson Annotations

1. Introduction

Jackson provides a number of annotations which help tweak various facets of JSON serialization and deserialization. In this guide, we present some important and commonly used Jackson annotations.

2. @JsonProperty

The annotation @JsonProperty is used to change the JSON property name used in serialization and deserialization. For example,

public class User {
    @JsonProperty("FirstName")
    private String firstName;
}

Output before and after:

// before
...
  "firstName" : "Harrison",
...

// after
  "FirstName" : "Harrison",
...

2.1. Confusion with required

The annotation @JsonProperty defines an attribute required which does not quite work the way it is expected. Despite being specified, it does not mark the property as required either during serialization or deserialization. It applies only when using @JsonProperty with @JsonCreator. For example, the following does not require the presence of the the property “FirstName“:

public class User {
    @JsonProperty(value="LastName", required=true)
    private String lastName;
}

2.2. @JsonProperty and @JsonCreator

@JsonProperty can be used with @JsonCreator to indicate the constructor to use when deserializing JSON. Consider the following class which does not implement a no-arguments default constructor but has a constructor taking appropriate arguments.

public class MyClass {
    private String firstName;
    private String lastName;

    public MyClass(String firstName,String lastName)
    {
	this.firstName = firstName;
	this.lastName = lastName;
    }
}

Create an instance of this class and serialize it to JSON.

MyClass obj = new MyClass("Harrison", "Ford");
System.out.println(mapper.writeValueAsString(obj));

// serialized to:
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
}

Deserializing this JSON results in a JsonMappingException. That is because Jackson cannot create an instance of the class in the absence of a default constructor.

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of sample.sample11$MyClass: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)

What if you do not want to add a default constructor due to design considerations? Jackson offers a solution: use @JsonCreator with @JsonProperty to properly mark the constructor. The constructor takes two arguments, both of which are marked required. With this change, Jackson is able to create an instance of MyClass with the proper arguments.

public class MyClass {
    private String firstName;
    private String lastName;
    private Address address;

    @JsonCreator
    public MyClass(@JsonProperty(value = "firstName",required = true) String firstName,
		   @JsonProperty(value = "lastName", required = true) String lastName)
    {
	this.firstName = firstName;
	this.lastName = lastName;
    }
}

3. @JsonIgnore

Property-level annotation used to ignore specified properties. These properties are ignored during both serialization and deserialization. For instance, the following property password is neither written to JSON nor read from JSON.

...
    @JsonIgnore
    private String password;
...

4. @JsonIgnoreProperties

Class level annotation used to ignore multiple properties.

@JsonIgnoreProperties({"bar", "baz"})
public class MyClass
{
    private String foo;
    private String bar;
    private Integer baz;
    ...
}

Additionally, you can use this annotation to ignore unknown properties during deserialization. If unknown properties are present in the JSON, you will get an UnrecognizedPropertyException.

@JsonIgnoreProperties(ignoreUnknown=true, {"bar", "baz"})
public class MyClass
{
    private String foo;
    private String bar;
    ...
}

Parsing the following JSON will not result in an exception due to specifying ignoreUnknown.

{
  "foo" : "value of foo",
  "bar" : "value of bar",
  "qux" : "value of qux"
}

5. @JsonIgnoreType

To ignore a particular class (or built-in type) during serialization and deserialization, use the @JsonIgnoreType annotation on the class. In the following, the MyClass.address property will not be serialized or deserialized.

@JsonIgnoreType
public class Address {
    private String address1;
    ...
}

public class MyClass {
    private Address address;
    private String firstName;
    private String lastName;
}

Note that MyClass.address property has bot been serialized. It will be ignored during deserialization.

{
  "firstName" : "Harrison",
  "lastName" : "Ford"
}

6. @JsonFormat

@JsonFormat is used to specify some extra details when serializing certain types especially dates.

The date field in the following class is serialized by default as a timestamp.

public class MyClass
{
    private Date createdDate = new Date();
}

// serialized to:
{
  "createdDate" : 1485913763410
}

Annotate the date field with @JsonFormat and use pattern to set the date format:

public class MyClass
{
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd@HH:mm:ss.SSSZ")
    private Date createdDate;
}

Serialization now shows the date in the specified format:

{
  "createdDate" : "2017-02-01@01:58:28.130+0000"
}

Deserialization also works as expected. If the date is not specified in the same format as required by the pattern, you get the following exception:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.util.Date from String "...": expected format "yyyy-MM-dd@HH:mm:ss.SSSZ" ...

7. @JsonUnwrapped

You can use @JsonUnwrapped to indicate to Jackson that a contained object should be unwrapped during serialization i.e. the contained object properties should be included among the properties of the parent. An example:

public class Address {
    private String address1;
    private String address2;
    private String city;
    private String state;
    private String zip;
}

public class MyClass {
    private String firstName;
    private String lastName;
    @JsonUnwrapped
    private Address address;
}

When an object of MyClass is serialized, the properties of address are included among the properties of MyClass:

{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address1" : "123 Main Street",
  "address2" : null,
  "city" : "Hollywood",
  "state" : "CA",
  "zip" : "33023"
}

To prevent clashes between the parent and child object properties, a prefix or suffix can be specified to be added to the child properties:

public class MyClass {
    private String firstName;
    private String lastName;
    @JsonUnwrapped(prefix="addr.")
    private Address address;
}

The resulting JSON is now:

{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "addr.address1" : "123 Main Street",
  "addr.address2" : null,
  "addr.city" : "Hollywood",
  "addr.state" : "CA",
  "addr.zip" : "33023"
}

During deserialization, either of the forms shown are accepted without errors.

// normal form
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address" : {
    "address1" : "123 Main Street",
    "address2" : null,
    "city" : "Hollywood",
    "state" : "CA",
    "zip" : "33023"
  }
}

// no prefix
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address1" : "123 Main Street",
  "address2" : null,
  "city" : "Hollywood",
  "state" : "CA",
  "zip" : "33023"
}

// with prefix
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "addr.address1" : "123 Main Street",
  "addr.address2" : null,
  "addr.city" : "Hollywood",
  "addr.state" : "CA",
  "addr.zip" : "33023"
}

8. @JsonGetter

This annotation can be used on a no-arguments method returning non-void, with the value specified to indicate the name of a logical property. An example, serializing an object of the class below will include a property “joe” defined as the value returned from the method theDate().

public class MyClass {
    private String firstName;
    private String lastName;

    @JsonGetter("joe")
    public Date theDate()
    {
	return new Date();
    }
}

// serialized to:
{
 "firstName" : "Harrison",
 "lastName" : "Ford",
 "joe" : 1485931403261
}

9. @JsonAnyGetter and @JsonAnySetter

In some instances, you may have a situation where a class has dynamic properties stored in a Map and these properties need to be exposed to JSON. In this situation, the getter method or the Map field can be marked with the @JsonAnyGetter annotation. An example will illustrate the point.

public class MyClass {
    private String firstName;
    private String lastName;
    private Address address;
    private Map<String,Object> moreProps = new HashMap<>();
}

// set properties
MyClass obj = new MyClass();
...
obj.setAddress(address);
obj.getMoreProps().put("born", "Chicago, Illinois");
System.out.println(mapper.writeValueAsString(obj));

// serialized to:
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "moreProps" : {
    "born" : "Chicago, Illinois"
  }
}

As expected, the Map field appears as a separate object within the container object. Using the @JsonAnyGetter merges the Map entries into the parent JSON.

public class MyClass {
    private String firstName;
    private String lastName;
    private Address address;
    private Map<String,Object> moreProps = new HashMap<>();

    @JsonAnyGetter
    public Map<String,Object> getMoreProps() {
        return moreProps;
    }
}

// create and set object properties here as before
MyClass obj = new MyClass();
...

// serialized to:
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "born" : "Chicago, Illinois"
}

That takes care of serialization. How about deserialization? JSON serialized for the above case cannot directly be used for deserialization as it results in an UnrecognizedPropertyException.

The solution is to use @JsonAnySetter on a method which accepts a key and a value to set the property. See below.

public class MyClass {
    ... // as before

    @JsonAnySetter
    public void setMore(String key,Object value)
    {
	moreProps.put(key, value);
    }
}

With this method definition and annotation in place, deserialization is also a breeze.

10. @JsonValue

@JsonValue can be used to serialize the complete state of an object using a single method rather than the usual serialization using properties. An example will help clarify the picture.

The following class marks the toString() method with @JsonValue. When serializing this object, Jackson uses the representation returned from this method as the value of the object. Note that the value returned is not valid JSON.

public class Address {
    private String address1;
    private String address2;
    private String city;
    private String state;
    private String zip;

    @JsonValue
    public String toString()
    {
	StringBuilder sbuf = new StringBuilder();
	sbuf.append(address1).append("|")
	    .append(address2).append("|")
	    .append(city).append("|")
	    .append(state).append("|")
	    .append(zip).append("|");
	return sbuf.toString();
    }
}

Serializing an instance of the above class yields:

"123 Main Street|null|Hollywood|CA|33023|"

Let us see how this works when included as a part of another class.

public class MyClass {
    private String firstName;
    private String lastName;
    private Address address;
}

After suitable initialization and serialization, we have the following JSON output. Note that the method annotated with @JsonValue was used for converting the value of Address to its representation.

{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address" : "123 Main Street|null|Hollywood|CA|33023|"
}

10.1. @JsonValue and @JsonCreator

Now, how do we deserialize this JSON into the proper object? We make use of the @JsonCreator annotation to mark a static factory method (or a constructor) which can create the object from its string representation. This method does the opposite of what the @JsonValue method does: it splits the string representation and sets the appropriate fields.

public class Address {
    private String address1;
    private String address2;
    ...

    @JsonCreator
    static public Address fromString(String value)
    {
	String[] values = value.split("\\|");
	Address obj = new Address();
	int index = 0;
	if ( index < values.length ) {
	    obj.setAddress1(values[index]);
	    index++;
	}
	if ( index < values.length ) {
	    obj.setAddress2(values[index]);
	    index++;
	}
	if ( index < values.length ) {
	    obj.setCity(values[index]);
	    index++;
	}
	if ( index < values.length ) {
	    obj.setState(values[index]);
	    index++;
	}
	if ( index < values.length ) {
	    obj.setZip(values[index]);
	    index++;
	}
	return obj;
    }
}

11. @JsonPropertyOrder

Sometimes you may need to specify the order in which the properties are serialized. By default properties are serialized in the order they are defined in the class. If this order is not satisfactory, you can use @JsonPropertyOrder to specify the order of appearance.

The following definition illustrates the point. Note the order in which the properties are serialized in JSON.

public class MyClass {
    private Address address;
    private String firstName;
    private String lastName;
}

// serialized by default as:
{
  "address" : {
    "address1" : "123 Main Street",
    "address2" : null,
    "city" : "Hollywood",
    "state" : "CA",
    "zip" : "33023"
  },
  "firstName" : "Harrison",
  "lastName" : "Ford"
}

Now applying the @JsonPropertyOrder annotation as shown rearranges the order to the required.

@JsonPropertyOrder(value = {"firstName", "lastName", "address"})
static public class MyClass {
    private Address address;
    ...
}

// serialized to:
{
  "firstName" : "Harrison",
  "lastName" : "Ford",
  "address" : {
    "address1" : "123 Main Street",
    "address2" : null,
    "city" : "Hollywood",
    "state" : "CA",
    "zip" : "33023"
  }
}

12. Mixin Annotations

Sometimes the class being used in JSON conversion may not be available for direct modification to add or remove annotations. Maybe the class is a part of a library and hence cannot be edited. How can we declare the annotations that we want on such classes? We use Mixins! Mixin classes can be declared with the desired annotations and added to the ObjectMapper using the addMixIn() method.

Example class:

public class MyClass
{
    private String foo;
    private String bar;
    private Integer baz;
    ...
}

Declare and add a mixin class like this. (The class can be a local class.)

@JsonIgnoreProperties(ignoreUnknown=true)
class Mixin {
    @JsonIgnore
    private Integer baz;
};
mapper.addMixIn(MyClass.class, Mixin.class);

Sample output from serialization. Note that property baz is ignored.

{
  "foo" : "value of foo",
  "bar" : "value of bar"
}

Deserializing this JSON does not cause an exception since ignoreUnknown is set in the mixin.

{
  "foo" : "value of foo",
  "bar" : "value of bar",
  "qux" : "value of qux"
}

Summary

In this article, we looked at some of the most common Jackson annotations for JSON serialization and deserialization.