Disable converting epoch to date on Springboot - java

I have the following springboot request:
#Data
#ToString
public class OffsetDate {
public OffsetDateTime time;
}
And my request goes:
{
"time" : 20000101
}
Right now, that is being converted to date during serialization: 1970-01-01T05:33:20.101Z - which I don't want to happen.
I need to be able to specify the format and fail if it's invalid without custom annotations (request code is actually autogenerated from swagger yaml, hence I cannot modify the request).
Is there a way to do that?

Related

Date format time on Spring Doc swagger API

I'm trying to generate the documentation from my springboot application using spring doc , this is some of the attributes of the class which is causing me issues:
public class user {
#JsonFormat(pattern = "yyyy-MM-dd")
private Date dateOfBirth;
}
With the Spring doc annotation, in the swagger i got this:
dateOfBirth* string($date-time)
"dateOfBirth": "2020-04-29T14:15:32.475Z"
while i would like to have this:
dateOfBirth* string($date)
"dateOfBirth": "2020-04-29"
How to do that? I think to be close to solution but i can't firugre out what i'm missing
I think the answer you are looking for is here: swagger date field vs date-time field
Date is an object DateTime for swagger, as it is really a DateTime object. Use the appropriate type, like LocalDate, they know how to handle that.
By the way, how would you expect Swagger to properly convert a Date Pattern into the appropriate type ? It's like too much magic. Swagger relies on thing that are common practices.
The JSONFormat won't change how swagger interpret your data.

How to define date example in MicroProfile OpenAPI

I tried to create minimal example of the problem.
Let's say we have simple return object:
public class Result {
#Schema(example = "2012-01-01")
private LocalDate sampleDate;
// omitted getter and setter
}
returned by simple JAX-RS endpoint:
#Path("/example")
#Produces(MediaType.APPLICATION_JSON)
public class Resource {
public List<Result> example() {
// omitted implementation
}
}
MicroProfile OpenAPI in Open Liberty will automatically generate following OpenAPI (Swagger) file:
openapi: 3.0.0
info:
title: Deployed APIs
version: 1.0.0
servers:
- url: http://localhost:9080/api
paths:
/example:
get:
operationId: example
responses:
default:
description: default response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Result'
components:
schemas:
Result:
type: object
properties:
sampleDate:
type: string
format: date
example: 2012-01-01
The problem is that embedded Swagger UI is displaying the date example as empty JS object:
I'm not sure if this is bug on Swagger UI side because if I don't provide any example in Java annotation = any example in OpenAPI file it will render the example as current day, e.g.:
[
{
"sampleDate": "2018-11-27"
}
]
Everything works correctly when I edit the OpenAPI output manually. Both single and double quotes fix the problem:
...
sampleDate:
type: string
format: date
example: '2012-01-01'
or
...
sampleDate:
type: string
format: date
example: "2012-01-01"
will produce expected output:
[
{
"sampleDate": "2012-01-01"
}
]
Question is how to change the annotations to get desired OpenAPI output.
Single quotes are automatically escaped:
#Schema(example = "'2012-01-01'")
private LocalDate sampleDate;
will produce:
...
sampleDate:
type: string
format: date
example: '''2012-01-01'''
Additional double quotes in Java doesn't have any effect on ouput:
#Schema(example = "\"2012-01-01\"")
private LocalDate sampleDate;
will produce same unquoted output:
...
sampleDate:
type: string
format: date
example: 2012-01-01
I know that I can write the OpenAPI yaml output manually but that is my last resort because I don't want to sacrifice automatic generation just because date examples are not behaving as I want. Maybe some OASFilter can be implemented to automatically wrap date's example values or I'm just missing something obvious here.
I've confirmed the behaviour that you're describing.
It the issue with Swagger-UI which is packaged with Microprofile OpenAPI, you could open issue here:
Swagger UI GitHub.
The value produced, without quotes is completely valid yaml, so UI
should be able to parse it as is.

Instantiating POJO (LocalDateTime) from YAML Properties File (Java & Spring Boot)

I am trying to load custom properties from a YAML properties file upon initialization using Spring Boot. I have found countless tutorials on how to do that, and they work. The problem is that I can't seem to find a way how to instantiate POJOS, such as for example LocalDateTime. My code is as shown below.
#Configuration
#ConfigurationProperties(prefix="default-film-showings")
public class FilmShowings {
private List<FilmShowing> filmShowings;
//Constructors, Getters, setters etc.
public static class FilmShowing {
private Integer id;
private Film film;
private Theatre theatre;
private LocalDateTime dateTime;
//Constructors, Getters, setters etc.
}
}
My YAML file is currently as follows
default-film-showings:
filmShowings:
- id: 1
dateTime: 2018-07-13 21:00:00
My problem is that I get the following error upon initialisation
Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'filmShowings[0].dateTime';
I also tried this variant
default-film-showings:
filmShowings:
- id: 1
dateTime:
date:
year: 2018
month: 7
day: 13
time:
hour: 21
minute: 0
second: 0
nano: 0
but I got the following error
Error creating bean with name 'filmShowings': Could not bind properties to FilmShowings
Any help? I looked at the following thread JSON Java 8 LocalDateTime format in Spring Boot but it didn't solve my problem.
On a similar note, is there any way to link the Film POJO attribute to another default property?
Say I have the following in my properties file
default-films:
films:
- id: 1
filmName: Spider-Man
can I add something like this too?
default-film-showings:
filmShowings:
- id: 1
film: default-films.films[0]
dateTime: whatever I need to do here to make it work
It is reading default-films.films[0] as string and thus not matching 'the YAML' object.
Any help?
Assuming Spring honors the #DateTimeFormat annotation in a #ConfigurationProperties class (I haven't verified that), you've declared the format to be DateTimeFormat.ISO.DATE_TIME which is 2011-12-03T10:15:30+01:00[Europe/Paris]. Your property file has 2018-07-13 21:00:00 which isn't any of the standard formats. How do you expect it to work?
Your datatype is LocalDateTime which doesn't have a concept of time zone, thus contradicting the ISO_DATE_TIME format. However, the time zone is optional is for ISO_DATE_TIME, so this may not be an issue.
Clearly, you're throwing spaghetti at the wall and hoping something would stick. Write a unit test and try to convert the string to whatever datetime object you want. Once you've done that, come back if you've a problem.
You should just adapt the setter in the configuration class.
if your yaml is:
default-film-showings:
filmShowings:
- id: 1
dateTime: 2018-07-13 21:00:00
then do this in your configuration class:
#Configuration
#ConfigurationProperties(prefix="default-film-showings")
public class FilmShowings {
private List<FilmShowing> filmShowings;
//Constructors, Getters, setters etc.
public static class FilmShowing {
private Integer id;
private Film film;
private Theatre theatre;
private LocalDateTime dateTime;
//Constructors, Getters, setters etc.
public void setDateTime(String dateTime) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd
HH:mm:ss");
LocalDateTime formatDateTime = LocalDateTime.parse(dateTime, formatter);
this.dateTime= formatDateTime;
}
}
}

Serialized data for requesting a Date value are different for JSON and XML

I have a Jersey Rest service that leverages the Jackson annotations to perform the serialization/deserialization for my service
but when jersey/jackson serializes my object with the below field i get two different values for the result for XML vs JSON requests
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date startDate;
Results
JSON: "startDate": "2016-02-01"
XML: <startDate>2016-02-01T00:00:00-05:00</startDate>
the json is showing correctly, but the XML results give all sorts of stuff I dont want at the end.
I've tried using other suggestions like
JsonSerializer<T> and JsonDeserializer<T>
but it gives me the same incorrect results
Am I missing an annotation to specifically handle XML?

json date format in spring-boot

I am using spring-boot and I have an entity class defined something like this
import org.joda.time.LocalDateTime;
#Entity
public class Project {
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime start_date;
...
...
}
When this class is converted to JSON, the field gets converted to the following string representation
{"start_date":[2014,11,15,0,0,0,0],...., ...}
I want to have the json response as yyyy-MM-dd.
I tried the #DateTimeFormat(iso = ISO.DATE) annotation and that did not help either.
Is there an easy way to do this conversion to proper json format ?
There are three things that you need to do to format the date as yyyy-MM-dd:
Add a dependency on com.fasterxml.jackson.datatype:jackson-datatype-joda. Judging by the output you're getting at the moment, I think you may already have this dependency.
Configure Jackson not to format dates as timestamps by adding spring.jackson.serialization.write-dates-as-timestamps: false to your application.properties file.
Annotate the LocalDataTime field or getter method with #JsonFormat(pattern="yyyy-MM-dd")
Note: You'll need to use Spring Boot 1.2 for step 2 to work.
Without additional dependency - the only thing I had to do is:
To take care send date from client as string object, in format yyyy/MM/dd
In Spring Boot application, to add annotation on the date field with
the same format
public class Foo
{
#JsonFormat(pattern = "yyyy/MM/dd")
private Date dueDate;
}
Using Spring Boot 2.3.5 version
Update
Another option, instead of step 2, to modify application.properties file, add there the format for any Date object:
spring.jackson.date-format=yyyy/MM/dd
You can use #JsonFormat annotation in and the desired pattern like this without using any dependency :
#JsonFormat(pattern="yyyy-MM-dd")
private Date created_At;
Took me some time struggling with Spring Boot Application + Date Format for my input so I'll try to resume what I saw.
If your date is argument to a function, you can use #DateTimeFormat(pattern = "yyyy-MM-dd") to define a pattern (ie. org.springframework.format.annotation.DateTimeFormat).
If your date is inside an object argument to the function, you can use #JsonFormat(pattern = "yyyy-MM-dd") to define a pattern (ie. com.fasterxml.jackson.annotation.JsonFormat)
If neither of these works, you can try changing your date Type, for me I had tu use org.joda.time.LocalDate in order to make it work with option 2 :
#JsonFormat(pattern = "dd/MM/yyyy")
private org.joda.time.LocalDate date;

Categories

Resources