Throw custom exception while deserializing the Date field using jackson in java

前端 未结 1 1878
执念已碎
执念已碎 2021-01-24 08:03

DTO:

@Getter
@Setter
@ToString
public class TestDto {

    @NotNull
    private String id;

    @NotNull
    @DateTimeFormat(pattern = \"YYYY-MM-DD\'T\'hh:mm:ss         


        
相关标签:
1条回答
  • 2021-01-24 08:56

    Since OP requested feature is not supported yet: https://github.com/FasterXML/jackson-annotations/issues/130

    Trying to do the same thing with a bit longer approach by using custom deserializer for a field timestamp

    Custom exception class:

    import com.fasterxml.jackson.core.JsonProcessingException;
    
    public class MyException extends JsonProcessingException {
        public MyException(String message) {
            super(message);
        }
    }
    

    Custom Deserializer class:

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
    
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.time.Instant;
    import java.util.Date;
    public class InstantDeserializer extends StdDeserializer<Instant> {
    
    public InstantDeserializer() {
        this(null); 
    } 
    
    public InstantDeserializer(Class<?> vc) {
        super(vc); 
    }
    
    private SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ss.SSS'Z'");
    
    @Override
    public Instant deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        Date date = null;
        try {
            date = sdf.parse(node.asText());
        } catch (Exception e) {
            throw new MyException("Instant field deserialization failed");
        }
        return date.toInstant();
    }
    }
    

    Updated TestDto class:

    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import lombok.Getter;
    import lombok.Setter;
    import lombok.ToString;
    import org.springframework.format.annotation.DateTimeFormat;
    
    import javax.validation.constraints.NotNull;
    import java.time.Instant;
    
    @Getter
    @Setter
    @ToString
    public class TestDto {
    
        @NotNull
        private String id;
    
        @NotNull
        @JsonDeserialize(using = InstantDeserializer.class)
        @DateTimeFormat(pattern = "YYYY-MM-DD'T'hh:mm:ss.SSS'Z'")
        private Instant timestamp;
    }
    

    Invalid Input request:

    {"timestamp":"4/23/2018 11:32 PM","id":"132"}
    

    Response:

    {
        "timestamp": 1552845180271,
        "status": 400,
        "error": "Bad Request",
        "message": "JSON parse error: Instant field deserialization failed; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Instant field deserialization failed (through reference chain: TestDto[\"timestamp\"])"
    }
    

    Valid Input Request:

    {"timestamp":"2018-04-23T11:32:22.213Z","id":"132"}
    

    Response:

    {
        "id": "132",
        "timestamp": {
            "epochSecond": 1514700142,
            "nano": 213000000
        }
    }
    

    If you do not like the way timestamp field is getting deserialized and would like to change that, this SO post will be helpful.

    0 讨论(0)
提交回复
热议问题