JSON Tutorial – Jackson Annotations – Part 2
JSON Tutorial – Jackson Annotations – Part 2
In this post we will continue to discuss how to Jackson Annotations are used and the affects they have on the serialization and deserialization of JSON / Java Objects. This post continues where we left off from JSON Tutorial – Jackson Annotations – Part 1 and addresses the remaining annotations in order to give you a better understanding of Jackson Annotations and how they are best used.
What’s Covered
Deserialization details
Serialization details
@JacksonInject
The Jackson Annotation @JacksonInject is used for indicating that value of annotated property will be “injected”, i.e. set based on value configured by ObjectMapper (usually on per-call basis).
@JsonPropertyOrder({"id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Address address;
@JacksonInject
public String source;
@JsonProperty("account-name")
private String accountName;
@JsonProperty("account-identifier")
private String accessIdentifier;
private ArrayList<Phone> phoneList = new ArrayList<Phone>();
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
}
json = "{\"id\":1,\"first-name\":\"Amaury\",\"last-name\":\"Valdes\", "
+ "\"account-name\":\"av50333\",\"account-identifier\":"
+ "\"AC652-87230F-128BE9-1897DA\",\"active-date\":"
+ "\"02/3/2015 21:37:19\"}";
InjectableValues inject = new InjectableValues.Std()
.addValue(String.class, "avaldes.com");
try {
User user2 = new ObjectMapper().reader(inject).forType(User.class)
.readValue(json);
System.out.println(user2);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
After @JacksonInject
In this example, you will notice that the source property that had the @JacksonInject annotation will now contain value of “avaldes.com”.
User [id=1, firstName=Amaury, lastName=Valdes, address=null, source=avaldes.com, accountName=av50333, accessIdentifier=AC652-87230F-128BE9-1897DA, phoneList=[], activeDate=Tue Feb 03 16:37:19 EST 2015]
@JsonAnySetter
The Jackson Annotation @JsonAnySetter can be used to define any method having two arguments (first argument is the the key, second argument is the value to be set). The primary purpose of this annotation is to act as a “fallback” handler for all otherwise unrecognized properties found from JSON. Once @JsonAnySetter annotation is used Jackson will route all “unrecognized” or “unknown” properties to use the same setter method in that Java object.
@JsonPropertyOrder({"id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Map<String, String> additionalProps = new HashMap<String, String>();
...
@JsonAnySetter
public void setAdditional(String key, String value) {
additionalProps.put(key, value);
}
...
Sample JSON with “unrecognized” properties
In this example, three of the properties do not have any corresponding setter/getter methods defined in my Java User class. However, after having placed the Jackson Annotation @JsonAnySetter just above the method setAdditional(), the properties position, years, and company-name which are all “unrecognized” to Jackson till this point will be directed to use the setAdditional() method during the deserialization process. As a result, all three will end up being pushed into the Map called additionalProps.
{
"id": 1,
"first-name": "Amaury",
"last-name": "Valdes",
"account-name": "av50333",
"account-identifier": "AC652-87230F-128BE9-1897DA",
"active-date": "02/03/2015 02:15:50",
"position": "SW Engineer",
"years": "4",
"company-name": "Nissan"
}
Reading JSON using ObjectMapper (Deserialization)
json = "{\"id\":1,\"first-name\":\"Amaury\",\"last-name\":"
+ "\"Valdes\",\"address\":null,\"account-name\":\"av50333\","
+ "\"account-identifier\":\"AC652-87230F-128BE9-1897DA\","
+ "\"active-date\":\"02/03/2015 02:15:50\",\"position\":"
+ "\"SW Engineer\",\"years\":\"4\",\"company-name\":"
+ "\"Nissan\"}";
try {
User user2 = new ObjectMapper().reader(User.class).readValue(json);
System.out.println(user2);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Output using @JsonAnySetter
As you can see, after printing out our User Java object we can see how these fields have all been placed in the additionalProps Map using the setAdditional() method.
User [id=1, firstName=Amaury, lastName=Valdes, address=null,
accountName=av50333, accessIdentifier=AC652-87230F-128BE9-1897DA,
additionalProps={position=SW Engineer, years=4, company-name=Nissan},
phoneList=[], activeDate=Mon Feb 02 21:15:50 EST 2015]
@JsonCreator
The Jackson Annotation @JsonCreator is used to instruct Jackson that the Java object has a constructor (a “creator”) that can be used to create the Java object from the JSON provided. In this scenario we annotate every argument in the constructor with JsonProperty or JacksonInject, to indicate name of property to bind to. We can also use the delegate creator, single argument constructor/factory method without JsonProperty annotation.
Let’s look at this example, which DOES NOT comply which either of the two main requirements stated above.
@JsonPropertyOrder({ "id", "first-name", "last-name" })
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Address address;
@JsonProperty("account-name")
private String accountName;
@JsonProperty("account-identifier")
private String accessIdentifier;
private ArrayList<Phone> phoneList = new ArrayList<Phone>();
private Map<String, String> additionalProps
= new HashMap<String, String>();
@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public User(int id,
String firstName,
String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
}
JACKSON EXCEPTION
The above example fails because Jackson is unable to find a suitable constructor it can use when performing the deserialization of the JSON to Java Object. If you look closely at our example, we did not create a default constructor for the User Class nor did add @JsonCreator annotation to this constructor with the proper JsonProperty annotations for each of the arguments. As a result we get the following error message:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.avaldes.model.User]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at Source …
@JsonCreator Annotation to the Rescue
By adding the Jackson annotation @JsonCreator to this constructor with the proper JsonProperty annotations for each of the argument we are able to use this constructor without having to create a default constructor.
@JsonPropertyOrder({ "id", "first-name", "last-name" })
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Address address;
@JsonProperty("account-name")
private String accountName;
@JsonProperty("account-identifier")
private String accessIdentifier;
private ArrayList<Phone> phoneList = new ArrayList<Phone>();
private Map<String, String> additionalProps
= new HashMap<String, String>();
@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
@JsonCreator
public User(@JsonProperty("id") int id,
@JsonProperty("first-name") String firstName,
@JsonProperty("last-name") String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
}
Output after using @JsonCreator Annotation
Now we are able to create the User object from the JSON
{
"id": 1,
"first-name": "Amaury",
"last-name": "Valdes",
"account-name": "av50333",
"account-identifier": "AC652-87230F-128BE9-1897DA",
"active-date": "02/03/2015 02:15:50"
}
Reading JSON using ObjectMapper (Deserialization)
json = "{\"id\":1,\"first-name\":\"Amaury\",\"last-name\":"
+ "\"Valdes\", \"account-name\":\"av50333\","
+ "\"account-identifier\":\"AC652-87230F-128BE9-1897DA\","
+ "\"active-date\":\"02/03/2015 02:15:50\"}";
try {
User user2 = new ObjectMapper().reader(User.class).readValue(json);
System.out.println(user2);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Output using @JsonCreator
User [id=1, firstName=Amaury, lastName=Valdes, accountName=av50333, accessIdentifier=AC652-87230F-128BE9-1897DA, activeDate=Mon Feb 02 21:15:50 EST 2015]
@JsonSetter
The Jackson Annotation @JsonSetter allows us to define which method will be used to set the appropriate field in the Java object by passing JSON property name as an argument in the @JsonSetter annotation. Jackson will then use the setter during the deserialization process. Use the Jackson annotation @JsonSetter as an alternative to using @JsonProperty. This is useful when the method names do not correspond to the property names in the JSON being used.
Let’s look at this example, which DOES NOT work correctly and see why.
JSON sample used
{
"id": 1,
"first-name": "Amaury",
"last-name": "Valdes",
"account-name": "av50333",
"account-identifier": "AC652-87230F-128BE9-1897DA",
"active-date": "02/03/2015 02:15:50"
}
User Object with missing @JsonSetter
@JsonPropertyOrder({"first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Address address;
private String accountName;
@JsonProperty("account-identifier")
private String accessIdentifier;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public int getUserId() {
return id;
}
@JsonSetter("id")
public void setUserId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccessIdentifier() {
return accessIdentifier;
}
public void setAccessIdentifier(String accessIdentifier) {
this.accessIdentifier = accessIdentifier;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
@Override
public String toString() {
return "User [id=" + id + ", firstName=" + firstName + ", lastName="
+ lastName + ", address=" + address + ", accountName="
+ accountName + ", accessIdentifier=" + accessIdentifier
+ ", activeDate=" + activeDate + "]";
}
}
JACKSON EXCEPTION
The above example fails because with the exception because Jackson is unable to find a suitable method it can use when performing the deserialization of the JSON to Java Object for the JSON property in question. As a result we get the following error message:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “account-name” (class com.avaldes.model.User), not marked as ignorable (8 known properties: “last-name”, “address”, “phones”, “active-date”, “first-name”, “accountName”, “account-identifier”, “id”])
at [Source: {“id”:1,”first-name”:”Amaury”,”last-name”:”Valdes”, “account-name”:”av50333″,”account-identifier”:”AC652-87230F-128BE9-1897DA”,”active-date”:”02/03/2015 02:15:50″}; line: 1, column: 69] (through reference chain: com.avaldes.model.User[“account-name”])
Looking closely at the above error message you are able to clearly see that the problem lies in the fact that Jackson is unable to find an appropriate method which can be used as setter for the JSON property of “account-name” during the deserialization process.
Reading JSON using ObjectMapper (Deserialization)
json = "{\"id\":1,\"first-name\":\"Amaury\",\"last-name\":"
+ "\"Valdes\", \"account-name\":\"av50333\","
+ "\"account-identifier\":\"AC652-87230F-128BE9-1897DA\","
+ "\"active-date\":\"02/03/2015 02:15:50\"}";
try {
User user2 = new ObjectMapper().reader(User.class).readValue(json);
System.out.println(user2);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Adding the missing @JsonSetter
In order to fix this problem, we simply need add the @JsonSetter prior to the setAccountName() method.
@JsonSetter("account-name")
public void setAccountName(String accountName) {
this.accountName = accountName;
}
Output after fixing the missing using @JsonSetter
User [id=1, firstName=Amaury, lastName=Valdes, accountName=av50333, accessIdentifier=AC652-87230F-128BE9-1897DA, activeDate=Mon Feb 02 21:15:50 EST 2015]
@JsonAnyGetter
The Jackson Annotation @JsonAnyGetter
@JsonPropertyOrder({"id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private Map<String, String> additionalProps = new HashMap<String, String>();
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
@JsonAnySetter
public void set(String key, String value) {
additionalProps.put(key, value);
}
public Map<String, String> get() {
return additionalProps;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
}
User user1 = new User();
user1.setUserId(1);
user1.setFirstName("Amaury");
user1.setLastName("Valdes");
user1.setAccountName("av50333");
user1.setAccessIdentifier("AC652-87230F-128BE9-1897DA");
user1.setActiveDate(new Date());
user1.set("position", "SW Engineer");
user1.set("company-name", "Nissan");
user1.set("years", "4");
ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
json = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(user1);
System.out.println(json);
} catch (IOException e) {
e.printStackTrace();
}
Output of JSON without @JsonAnyGetter
What happened? Looks like we’re missing some of our properties. Remember, we had passed in position, company-name and years in our User object.
{
"first-name" : "Amaury",
"last-name" : "Valdes",
"account-name" : "av50333",
"account-identifier" : "AC652-87230F-128BE9-1897DA",
"active-date": "02/02/2015 19:43:19",
"id" : 1
}
Output of JSON with @JsonAnyGetter
{
"first-name" : "Amaury",
"last-name" : "Valdes",
"account-name" : "av50333",
"account-identifier" : "AC652-87230F-128BE9-1897DA",
"active-date": "02/02/2015 19:43:19",
"position" : "SW Engineer",
"years" : "4",
"company-name" : "Nissan"
"id" : 1
}
@JsonGetter
The Jackson Annotation @JsonGetter allows us to define which method will be used to get the appropriate field from the Java object by passing JSON property name as an argument in the @JsonGetter annotation. Jackson will then use the getter during the serialization process for the conversion from POJO to JSON. Use the Jackson annotation @JsonGetter as an alternative to using @JsonProperty.
Let’s look at this example, which DOES NOT show the correct JSON property names and see why…
We would like to see the serialized JSON to have property names account-name and account-identifer.
User Object with missing @JsonGetter
@JsonPropertyOrder({ "id", "first-name", "last-name" })
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
private String accountName;
private String accessIdentifier;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccountIdentifier() {
return accessIdentifier;
}
public void setAccessIdentifier(String accessIdentifier) {
this.accessIdentifier = accessIdentifier;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
@Override
public String toString() {
return "User [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", accountName=" + accountName
+ ", accessIdentifier=" + accessIdentifier
+ ", activeDate=" + activeDate + "]";
}
}
JSON produced by missing @JsonGetter
If you look closely you will notice that the JSON is fine syntactically. However, the property names are not following the standards that we wanted.. Instead of being in camelCase which is how they are defined in Java, we wanted the properties to be hyphen delimited as stated earlier.
{
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"accountName" : "av50333",
"accountIdentifier" : "AC652-87230F-128BE9-1897DA",
"active-date": "02/02/2015 19:46:03"
}
Since we did not annotate the variable names using @JsonProperty and we did not annotate the methods with @JsonGetter and the property names we wanted Jackson will serialize the Java Object using the variable names available which happen to be written in camelCase. In our example, Jackson serialized the two properties with accountName and accountIdentifier
Adding @JsonGetter to our User Class
@JsonGetter("account-name")
public String getAccountName() {
return accountName;
}
@JsonGetter("account-identifer")
public String getAccountIdentifier() {
return accessIdentifier;
}
Output of JSON with @JsonGetter
{
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"account-name" : "av50333",
"account-identifer" : "AC652-87230F-128BE9-1897DA",
"active-date": "02/02/2015 19:46:03"
}
@JsonPropertyOrder
The Jackson Annotation @JsonPropertyOrder is used to define ordering, even partial ordering, when serializing object properties to JSON. Properties included in annotation declaration will be serialized first (in defined order), followed by any properties not included in the definition.
@JsonPropertyOrder({"id", "first-name", "last-name"})
public class User {
private int id;
private String firstName;
private String lastName;
private Address address;
private Phone mobilePhone;
private Phone homePhone;
private Phone workPhone;
}
Before @JsonPropertyOrder
{
"id" : 1,
"address" : {
"address1" : "100 Main Street",
"address2" : null,
"city" : "Eureka",
"state" : "Montana",
"zipCode" : "59917"
},
"mobilePhone" : {
"phoneType" : "Apple iPhone6",
"phoneNumber" : "800-222-5454",
"phoneSystemIdentifier" : "VERIZON"
},
"homePhone" : null,
"workPhone" : null,
"first-name" : "Amaury",
"last-name" : "Valdes"
}
After adding @JsonPropertyOrder
{
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"address" : {
"address1" : "100 Main Street",
"address2" : null,
"city" : "Eureka",
"state" : "Montana",
"zipCode" : "59917"
},
"mobilePhone" : {
"phoneType" : "Apple iPhone6",
"phoneNumber" : "800-222-5454",
"phoneSystemIdentifier" : "VERIZON"
},
"homePhone" : null,
"workPhone" : null
}
Using @JsonPropertyOrder with Alphabetic=true
You can also decide to alphabetize the JSON properties. Jackson provides you with the ability to easily do this with parameter (alphabetic=true).
@JsonPropertyOrder(alphabetic=true)
public class User {
private int id;
private String firstName;
private String lastName;
private Address address;
private Phone mobilePhone;
private Phone homePhone;
private Phone workPhone;
}
Alphabetizing JSON Elements
{
"address" : {
"address1" : "100 Main Street",
"address2" : null,
"city" : "Eureka",
"state" : "Montana",
"zipCode" : "59917"
},
"first-name" : "Amaury",
"homePhone" : null,
"id" : 1,
"last-name" : "Valdes",
"mobilePhone" : {
"phoneType" : "Apple iPhone6",
"phoneNumber" : "800-222-5454",
"phoneSystemIdentifier" : "VERIZON"
},
"workPhone" : null
}
@JsonRawValue
The Jackson Annotation @JsonRawValue tells Jackson that the annotated method or field should be serialized by including the literal String value of the property “as is” directly in the JSON output.
@JsonPropertyOrder({ "id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
@JsonRawValue
@JsonProperty("corporate-account")
public String corporateAccount =
"{\"corp-number:\" 188, \"phone\": \"800-283-8888\"}";
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
@Override
public String toString() {
return "User: {id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", activeDate="
+ activeDate + "}";
}
}
Output of JSON with @JsonRawValue
With the @JsonRawValue annotation Jackson serializes this into the following JSON:
{
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"active-date" : "02/02/2015 19:52:38",
"corporate-account" : {"corp-number:" 188, "phone": "800-283-8888"},
}
@JsonValue
The Jackson Annotation @JsonValue tells Jackson that the annotated method will be used to serialize the object to JSON and it should make no attempt to serialize the Java object itself. This Jackson annotation has a restriction that AT MOST one method can be annotated with this annotation, if violated an exception will be thrown.
JACKSON EXCEPTION
If you somehow added @JsonValue annotation to more than one method in a given class Jackson would generate the following exception(s):
- com.fasterxml.jackson.databind.JsonMappingException: Problem with definition of [AnnotedClass com.avaldes.model.User]: Multiple value properties defined
- java.lang.IllegalArgumentException: Problem with definition of [AnnotedClass com.avaldes.model.User]: Multiple value properties defined
@JsonPropertyOrder({ "id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
@Override
@JsonValue
public String toString() {
return "User: {id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", activeDate="
+ activeDate + "}";
}
}
Output of JSON with @JsonValue
With the @JsonValue annotation Jackson serializes this into the following which is not really value JSON.
"User: {id=1, firstName=Amaury,
lastName=Valdes, activeDate=Fri Mar 11 12:51:22 EST 2016}"
Converting toString to Produce JSON using @JsonValue
@Override
@JsonValue
public String toString() {
return "{\"id\":" + id + ", \"firstName\":\"" + firstName
+ "\", \"lastName\":\"" + lastName + "\", \"activeDate\":"
+ "\"" + activeDate + "\"}";
}
Output of JSON with @JsonValue
Not quite there yet… So what else can we do… As you can see, Jackson takes all the \” and outputs them verbatim which is not exactly what we need here. Let do one more thing. We will need to also add @JsonRawValue annotation to fix the output and get it to where we want it.
"{\"id\":1, \"firstName\":\"Amaury\", \"lastName\":
\"Valdes\", \"activeDate\":\"Fri Mar 11 12:58:28 EST 2016\"}"
Converting toString to Produce JSON using @JsonValue and @JsonRawValue
@Override
@JsonValue
@JsonRawValue
public String toString() {
return "{\"id\":" + id + ", \"firstName\":\"" + firstName
+ "\", \"lastName\":\"" + lastName + "\", \"activeDate\":"
+ "\"" + activeDate + "\"}";
}
Output of JSON with @JsonValue and @JsonRawValue
Now we have it.
{"id":1, "firstName":"Amaury", "lastName":"Valdes",
"activeDate":"Fri Mar 11 13:03:05 EST 2016"}
@JsonRootName
The Jackson Annotation @JsonRootName tells Jackson to wrap the object with a top-level element, if wrapping is enabled. This annotation will take the name as a parameter.
PLEASE NOTE
Wrapping must be enabled before JsonRootName will work. Failure to do so will not cause any exception, but will prevent Jackson from actually performing any wrapping.
@JsonRootName("user")
@JsonPropertyOrder({ "id", "first-name", "last-name"})
public class User {
private int id;
@JsonProperty("first-name")
private String firstName;
@JsonProperty("last-name")
private String lastName;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="MM/dd/yyyy HH:mm:ss")
@JsonProperty("active-date")
private Date activeDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getActiveDate() {
return activeDate;
}
public void setActiveDate(Date activeDate) {
this.activeDate = activeDate;
}
@Override
public String toString() {
return "User [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName
+ ", activeDate=" + activeDate + "]";
}
}
Output of JSON with @JsonRootName with Wrapping Disabled
{
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"active-date" : "02/02/2015 20:31:23",
}
How to Enable Wrapping
ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
Output of JSON with @JsonRootName with Wrapping Enabled
{
"user" : {
"id" : 1,
"first-name" : "Amaury",
"last-name" : "Valdes",
"active-date" : "02/02/2015 20:32:48",
}
}
@JsonSubTypes
The Jackson Annotation @JsonSubTypes tells Jackson the subtype of the annotated type.

Leave a Reply