user6077173
user6077173

Reputation:

Jackson ObjectMapper : Issues with date serialization and deserialization

I would like to disable lenient option in Jackson Deserializer to deserialize Date fields strictly.

Basically, I would like the below code to throw Exception instead of parsing 33-Aug-2016 as 02-Sep-2016.

1. Order.java

package com.test.date;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;

public class Order {

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MMM-yyyy")
    private Date orderDate;

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }

    public String getFormattedDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
        return "[ " + sdf.format(getOrderDate()) + " ]";
    }

}

2. TestJackson.java

package com.test.date;

import java.io.IOException;
import java.text.SimpleDateFormat;

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

public class TestJackson {

    public static void main(String[] args) throws JsonParseException,
            JsonMappingException, IOException {

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
        sdf.setLenient(false);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(sdf);
        Order order = mapper.readValue("{\"orderDate\" : \"33-Aug-2016\"}",
                Order.class);
        System.out.println(order.getFormattedDate());

    }

}

Output

[ 02-Sep-2016 ]

I can implement my own Deserializer class to do this, but I am looking for some annotation based or object mapper settings approach.

UPDATE:

I decided to go with custom Deserializer implementation and found another issue, but with Serialization now. The updated codes are for as shown below:

1. Order.java

package com.test.date;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class Order {

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MMM-yyyy")
    @JsonDeserialize(using = DateDeserializer.class)
    private Date orderDate;

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }

    @JsonIgnore
    public String getFormattedDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
        return "[ " + sdf.format(getOrderDate()) + " ]";
    }

}

With custom deserializer, validation of dates work perfectly. However, serialization of the same object has issues. Please see below:

2. TestJackson.java

package com.test.date;

import java.io.IOException;

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

public class TestJackson {

    public static void main(String[] args) throws JsonParseException,
            JsonMappingException, IOException {

        ObjectMapper mapper = new ObjectMapper();
        Order order = mapper.readValue("{\"orderDate\" : \"22-Aug-2016\"}",
                Order.class);


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

    }

}

Output

{"orderDate":"21-Aug-2016"}

From where does this one day difference come into picture?

Is it mandatory to provide custom implementation of Serializer if we use a custom Deserializer?

Upvotes: 2

Views: 6157

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279880

The @JsonFormat annotation on the property overrides the SimpleDateFormat registered with the ObjectMapper. Get rid of the @JsonFormat and Jackson will use only the supplied SimpleDateFormat to parse the date and fail because of the

sdf.setLenient(false);

As far as I know, @JsonFormat does not have a Feature you can set to control leniency.

Upvotes: 1

Related Questions