In the Restful Web services application, we parse a JSON request string which is then mapped to a java class. The JSON string is unmarshalled to the java class using the Jackson library. If the JSON string consists of properties that cannot be mapped to java class attributes, then we encounter UnrecognizedPropertyException. Let’s understand this with an Illustration given below.
Illustration:
We have an Employee class with attributes like name, id, department and salary. We then create a json string with all these properties. We will then try to deserialize the JSON string to Employee class.
In setting up in eclipse, we need to create a maven project and add the following dependency in the ‘pom.xml file’.
<dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.3</version> </dependency> </dependencies>
This will download the following jars in our project.
jackson-databind-2.2.3.jar jackson-annotations-2.2.3.jar jackson-core-2.2.3.jar
Now proceeding further, let us serialize and Deserialize using the Jackson library where we use Jackson library to serialize employee object to json file which is created in src/main/resources folder. Jackson’s library also has APIs which pretty much print the json file as implemented below.
Example
Java
// Java Program to Serialize and Deserialize // Using the Jackson library // Importing input output classes // Importing Jackson classes import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.io.File; import java.io.IOException; // Helper class class Employee { // Member variables of this class private String id; private String name; private String deptName; private double salary; // Member functions public String getId() { return id; } public void setId(String id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this .deptName = deptName; } public double getSalary() { return salary; } public void setSalary( double salary) { this .salary = salary; } } // Main class class GFG { // Main driver method public static void main(String[] args) { // creates an object mapper instance ObjectMapper mapper = new ObjectMapper(); // creates an employee instance. Employee employee = generateEmployee(); // java object to json // Try block to check for exceptions try { // Serializes the java object to json and // creates a file in src/main/resources mapper.writeValue( new File( "/home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/json-parsing/src/main/resources/emp.json" ), employee); // Creating a json string String empJson = mapper.writeValueAsString(employee); // Print and display System.out.println(empJson); // Pretty print String empJsonPrettyPrint = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(employee); System.out.println( "Pretty print format" ); System.out.println(empJsonPrettyPrint); } // Catch block 2 // Catch block to handle exceptions // related to json generation catch (JsonGenerationException e) { // Print the exception along with line number // using printStackTrace() method e.printStackTrace(); } // Catch block 2 // Catch block to handle exceptions // related to json mapping catch (JsonMappingException e) { e.printStackTrace(); } // Catch block 3 // Catch block to handle basic exceptions catch (IOException e) { e.printStackTrace(); } // Convert to a json string } private static Employee generateEmployee() { Employee employee = new Employee(); employee.setId( "e01010" ); employee.setName( "Jane" ); employee.setDeptName( "Sales" ); employee.setSalary( 100000.00 ); return employee; } } |
Output:
{"id":"e01010","name":"Jane","deptName":"Sales","salary":100000.0} Pretty print format { "id" : "e01010", "name" : "Jane", "deptName" : "Sales", "salary" : 100000.0 }
The file emp.json gets created in src/main/resources folder.
{"id":"e01010","name":"Jane","deptName":"Sales","salary":100000.0}
Now let us understand UnrecognizedPropertyException through an example when do we get this exception while parsing json files.
Implementation:
- We create a json file with a new property added as phoneNumber. However, this property is not present in the Employee class.
- When Jackson library tries to unmarshal/deserialize the json field values to the class attributes, it cannot recognize this property and it throws UnrecognizedPropertyException.
- We create a file emp1.json in src/main/resources. The file emp1.json has a new property phoneNumber which is not a part of Employee class.
{"id":"e01010","name":"Jane","deptName":"Sales","salary":100000.0,"phoneNumber": 98218281812}
Example
Java
// Java Program to Illustrate UnrecognizedPropertyException // While parsing json files // Importing input output classes import java.io.*; // Class 1 // Helper class class Employee { // Member variables of this class private String id; private String name; private String deptName; private double salary; // Member functions of this class public String getId() { return id; } public void setId(String id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this .deptName = deptName; } public double getSalary() { return salary; } public void setSalary( double salary) { this .salary = salary; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", deptName=" + deptName + ", salary=" + salary + "]" ; } } // Class 2 // Main class class GFG { // Main driver method public static void main(String[] args) { // Creating an object of ObjectMapper class ObjectMapper mapper = new ObjectMapper(); // Try block to check for exceptions try { // mapper reads from json file and deserializes // it to Employee object Employee emp = mapper.readValue( new File( "/home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/json-parsing/src/main/resources/emp1.json" ), Employee. class ); System.out.println( "Reading values of employee attributes from a json file" ); System.out.println(emp.toString()); } // Catch Block 1 // Handling json parsing exception catch (JsonParseException e) { // Print and display the exception along with // line number using printStackTrace() method e.printStackTrace(); } // Catch Block 2 // Handling json mapping exception catch (JsonMappingException e) { e.printStackTrace(); } // Catch Block 3 // Catch block to handle basic exceptions catch (IOException e) { e.printStackTrace(); } } } |
Output:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "phoneNumber" (class com.sample.json.Employee), not marked as ignorable (4 known properties: , "deptName", "salary", "id", "name"]) at [Source: /home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/json-parsing/src/main/resources/emp1.json; line: 1, column: 93] (through reference chain: com.sample.json.Employee["phoneNumber"]) at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79) at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555) at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1160) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:315) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1988) at com.sample.json.TestParsingException.main(TestParsingException.java:19)
Note: The exception states that it is unable to recognize the property phoneNumber which is a part of emp1.json file. This is because it is unable to map this property with the attributes of the Employee class.
Now let us discuss a way out to get rid of this exception. Below are two ways with which we can incorporate for the same which are as follows:
- Disabling the object mapper to deserialize on unknown properties.
- Providing an annotation at the class level @JsonIgnoreProperties.
Method 1: Disabling the object mapper to deserialize on unknown properties.
In order to solve this issue, we disable the object mapper to deserialize on unknown properties. So the object mapper will unmarshal/deserialize only those properties from json file which are mapped to the java class. We have emp1.json which is similar to the previous example.
emp1.json {"id":"e01010","name":"Jane","deptName":"Sales","salary":100000.0,"phoneNumber": 98218281812}
Example
Java
// Java Program to Remove UnrecognizedPropertyException by // Disabling the object mapper to deserialize on unknown // properties. package com.sample.json; // Importing input output classes import java.io.*; // Class 1 // Helper class public class Employee { // Member variables of this class private String id; private String name; private String deptName; private double salary; // Member methods of this class public String getId() { return id; } public void setId(String id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this .deptName = deptName; } public double getSalary() { return salary; } public void setSalary( double salary) { this .salary = salary; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", deptName=" + deptName + ", salary=" + salary + "]" ; } } // Class 2 // Main class class GFG { // Main driver method public static void main(String[] args) { // Creating an object of ObjectMapper class ObjectMapper mapper = new ObjectMapper(); // Try block to check for exceptions try { // Disabling the mapper object to deserialize // properties which cannot be mapped to java // class mapper.disable(DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES); // mapper reading the json file and // deserializes it to employee object Employee emp = mapper.readValue( new File( "/home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/json-parsing/src/main/resources/emp1.json" ), Employee. class ); // Display message only System.out.println( "Reading values of employee attributes from a json file" ); // Print and display System.out.println(emp.toString()); } // Catch block to handle exceptions // Catch block 1 to deal with json parsing exception catch (JsonParseException e) { e.printStackTrace(); } // Catch block 2 to deal with json mapping exception catch (JsonMappingException e) { e.printStackTrace(); } // Catch block 2 to deal with basic I/O exceptions catch (IOException e) { e.printStackTrace(); } } } |
Output:
Reading values of employee attributes from a json file Employee [id=e01010, name=Jane, deptName=Sales, salary=100000.0]
Method 2: Providing an annotation at the class level @JsonIgnoreProperties
Another approach is to provide an annotation at the class level @JsonIgnoreProperties(ignoreUnknown = true). This annotation tells jackson to ignore those attributes which cannot be mapped to java class. This is the same emp1.json from the previous example.
emp1.json {"id":"e01010","name":"Jane","deptName":"Sales","salary":100000.0,"phoneNumber": 98218281812}
Example
Java
// Java Program to Remove UnrecognizedPropertyException by // Providing an annotation at the class level // @JsonIgnoreProperties // Importing required classes import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.io.*; @JsonIgnoreProperties (ignoreUnknown = true ) // Class 1 // Helper class public class Employee { // Member variables of this class private String id; private String name; private String deptName; private double salary; // Mamber functions of this class public String getId() { return id; } public void setId(String id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this .deptName = deptName; } public double getSalary() { return salary; } public void setSalary( double salary) { this .salary = salary; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", deptName=" + deptName + ", salary=" + salary + "]" ; } } // Class 2 // Main class class GFG { // Main driver method public static void main(String[] args) { // Creating an object of ObjectMapper class ObjectMapper mapper = new ObjectMapper(); // Try block to check for exceptions try { // Mapper reads from emp1.json and deserializes // it to employee object. It ignores those // properties which are not mapped to java class Employee emp = mapper.readValue( new File( "/home/suchitra/Desktop/suchitra/projects/java-concurrency-examples/json-parsing/src/main/resources/emp1.json" ), Employee. class ); System.out.println( "Reading values of employee attributes from a json file" ); System.out.println(emp.toString()); } // Catch block to handle the exceptions // Catch Block 1 catch (JsonParseException e) { // Print the exception along with line number // using printStackTrace() method e.printStackTrace(); } // Catch Block 2 catch (JsonMappingException e) { e.printStackTrace(); } // Catch Block 3 // Handling basic I/O exceptions catch (IOException e) { e.printStackTrace(); } } } |
Output:
Reading values of employee attributes from a json file Employee [id=e01010, name=Jane, deptName=Sales, salary=100000.0]