I'm trying to serialize a Timestamp Object to a JSON. But the object in the JSON is displayed as seconds.
This is a snippet of my POJO:
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class TimeAndDateDetail{
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh.mm.ss")
private Timestamp timeAndDate;
public Timestame getTimeAndDate() {return timeAndDate; }
public void setTimeAndDate(Timestamp timeAndDate){
this.timeAndDate = timeAndDate;
}
}
This is my output:
{
"timeAndDate": 1583038800000
}
Why is this happening? And how can I get it to keep its original format?
You can annotate the field with #JsonFormat to specify the format, that the timestamp will be serialized. Here is an example:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
Looks like you are using jackson, and this is the default behaviour of it.
best way is to disable the related object mapper feature:
objectMapper
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
Related
Trying to deserialize date with specific pattern from json file.
Object which I want to receive from json file:
#Data
public class MyClass {
#DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime date;
}
Json file:
{
"date" : "2017-01-01T00:00:59.000UTC"
}
Code example how I want to receive it:
ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);
Actual result:
com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type `java.time.LocalDateTime` from String "2017-01-01T00:00:59.000UTC":
Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException)
Text '2017-01-01T00:00:59.000UTC' could not be parsed, unparsed text found at index 23
at [Source: (File); line: 2, column: 11] (through reference chain: com.example.MyClass["date"])
How to deserialize current date pattern?
The date format that you are using is incorrect.
Instead of: yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'
it should be: yyyy-MM-dd'T'HH:mm:ss.SSSz
Secondly, you need to use #JsonFormat to specify the date format.
#JsonFormat which is defined in jackson-databind package gives you more control on how to format Date and Calendar values according to SimpleDateFormat.
By using this, the POJO MyClass would look something like this:
#Data
public class MyClass {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSz", timezone = "UTC")
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime date;
}
Now, if you try to deserialize using:
ObjectMapper mapper = new ObjectMapper();
MyClass clazz = mapper.readValue(new File("MyFile.json"), MyClass.class);
System.out.println(myClass);
Then the process would go through, producing a result something like this:
MyClass{date=2017-01-01T00:00:59.000}
Your date is in incorrect format (with UTC as text simply appended), but you can solve it by custom formatter.
public class Test {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
MyClass localDateTime = objectMapper.readValue("{\"date\":\"2017-01-01T00:00:59.000UTC\"}", MyClass.class);
System.out.println(localDateTime.date);
}
#Data
public static class MyClass {
#JsonDeserialize(using = CustomDeserializer.class)
private LocalDateTime date;
}
public static class CustomDeserializer extends LocalDateTimeDeserializer {
public CustomDeserializer() {
super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
protected CustomDeserializer(LocalDateTimeDeserializer base, Boolean leniency) {
super(base, leniency);
}
#Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String substring = jsonParser.getText().substring(0, jsonParser.getText().indexOf("U"));
return LocalDateTime.parse(substring, _formatter);
}
}
}
Try removing #JsonDeserialize. (In any case, you are trying to deserialize your date into LocalDateTime but it has time zone info, you would need to try ZonedDateTime or OffsetDateTime). And change the line
#DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'")
to
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
Here is the link to the question that has a full answer for you: Spring Data JPA - ZonedDateTime format for json serialization
I have a spring app in which I am using the #JsonFormat annotation to deserialize a date format. But when I sent an array of elements my entire payload fails even if one of the entries have an invalid date.
Is there a way I can surpass this by gracefully handling this exception, by either replacing the failed date with a default value or ignoring that array entry.
jackson.version: 2.7.5,
spring.version: 5.0.0.RELEASE
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
private Date date;
You could write a custom deserializer for your class where you set a default value in case something goes wrong. Something like:
public class MyJsonDateDeserializer extends JsonDeserializer<Date>
{
#Override
public Date deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String date = jsonParser.getText();
try {
return format.parse(date);
} catch (ParseException e) {
return new Date();
}
}
}
Then on your class you could do something like:
class MyClass {
//...Fields
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
#JsonDeserialize(using = MyJsonDateDeserializer.class)
private Date date;
//...Fields
}
You could also add #JsonIgnoreProperties(ignoreUnknown = true) over your class if you know that its value is not necessary always.
I have the following JSON string in REST response:
"09:41:50 CET"
For the corresponding POJO mapper class has a Date type for this field. So I've tried Jackson and GSON to map JSON to Java Object, but both failed with the following messages:
GSON: java.text.ParseException: Failed to parse date ["09:41:50 CET"]: Invalid number: 09:4
Jackson: InvalidFormatException: Cannot deserialize value of type `java.util.Date` from
String "09:41:50 CET": not a valid representation
Sadly I cannot modify in the POJO class the type to string or anything else, because I get those POJO classes from mvn dependency.
Try with this:
public static void main(String[] args) throws ParseException {
String jsonStr = "{ \"date\" : \"09:41:50 CET\" }";
Gson gson = new GsonBuilder().setDateFormat("HH:mm:ss").create();
JsonElement element = gson.fromJson (jsonStr, JsonElement.class);
OnlyDate date =gson.fromJson(element, new TypeToken<OnlyDate>(){}.getType());
System.out.println(date.getDate());
}
My example DTO is:
public class OnlyDate implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#SerializedName("date")
private Date date ;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
You have to specify the dateFormat of your gson Element
Not sure what kind of rest you have however if you are using spring rest you can do it by implementing custom Converter check the example at https://www.baeldung.com/spring-mvc-custom-data-binder.
Since Jackson v2.0, you can use #JsonFormat annotation directly on Object members;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss", timezone="CET")
private Date date;
In my browser debug, I can see that there is a date parameter inside my v object (Wed Mar 25 2015 03:00:00 GMT+0300 (Turkey Standard Time)),full text string format.
function saveVehicle(v) {
return $http.post('/shipment/vehicle/save', v).then(function(response) {
return response.data;
})
The problem is in my requestmapping debug, that date parameter comes with null. The server side coding is like this:
#RequestMapping(value="/vehicle/save", method = RequestMethod.POST)
public Vehicle saveVehicle(#RequestBody Vehicle v){
return vehicleRepository.save(v);
}
And my Vehicle model is like this:
#Entity
#Table(name = "VEHICLE", schema = "VV")
public class Vehicle {
#Column(name = "LOADING_DT")
#JsonSerialize(using = TfJsonDateSerializer.class)
#JsonDeserialize(using = TfJsonDateDeSerializer.class)
private Date loadingDate;
You need to map your object 'v' send from browser into the Java Object 'Vehicle'.
Usually using a json mapper or custom mapping from Map to your Vehicle pojo.
also try to POST a well formed object, that ressambles by parameter names your pojo.
v = {
"loading_date": new Date()
}
$http.post(..., v);
Additionally, I see that you're using custom (de)serializers, so please either post their code or be sure that they perform correctly, according to how the JS is serializing the date value
best
nas
It might be that the property into the request body doesn't have the same name of the java Vehicle#loadingDate attribute.
Assuming your request body has an attribute called loading_date, you have to map that name to the java attribute as follows:
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonProperty("loading_date")
private Date loadingDate;
Also, it might be a good idea to define a string conversion for dates:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
#JsonProperty("loading_date")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "UTC")
private Date loadingDate;
and add getters and setters in case you forgot:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
#JsonProperty("loading_date")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "UTC")
private Date loadingDate;
public Date getLoadingDate() {
return loadingDate;
}
public void setLoadingDate(Date loadingDate) {
this.loadingDate = loadingDate;
}
I've got model and field like this:
#Element(name = "TIMESTAMP")
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime date;
In response I received:
<TIMESTAMP>2016-05-04T13:13:42.000</TIMESTAMP>
but during parsing xml to model I have error:
"message": "org.simpleframework.xml.core.PersistenceException: Constructor not matched for class java.time.LocalDateTime",
I also tried with:
#Element(name = "TIMESTAMP")
#DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
private LocalDateTime date;
and this still doesn't work. Any Idea ? I am using springframework.xml lib.
The problem is by default simplexml lib doesn't know how to serialize/deserialize new Java8 date types.
In order to succeed you need to use custom converter.
Example entity (see the special #Convert annotation)
public class Entity {
#Element(name = "TIMESTAMP")
#Convert(LocalDateTimeConverter.class)
private LocalDateTime date;
// omitted
}
Special converter
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
public LocalDateTime read(InputNode node) throws Exception {
String name = node.getValue();
return LocalDateTime.parse(name, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
public void write(OutputNode node, LocalDateTime input) {
String value = input.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
node.setValue(value);
}
}
Usage
Strategy strategy = new AnnotationStrategy();
Persister persister = new Persister(strategy);
Entity serializedEntity = persister.read(Entity.class, xmlInputStream);
Full source is available on GitHub