In my request model, I have a field like
#NotNull
#Schema(example = "19680228", type = "String", format = "yyyyMMdd", pattern = "([0-9]{4})(?:[0-9]{2})([0-9]{2})", required = true, nullable = false)
#JsonDeserialize(using = CustomDateDeserializer.class)
private OffsetDateTime birthDate;
My birthday is of OffsetDateTime type, however, request comming in contains only date portion in format yyyyMMdd. This is requirement and cannot be changed. And this is OK, I already take care of that with my CustomDateDeserializer and it is all working fine.
Based on OpenAPI documentation and some post (https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#data-types, What is the correct way to declare a date in an OpenAPI / Swagger-file?), I know that OpenAPI supports ISO8601 date and date-time, in which case, no pattern is needed and type should be provided as date or date-time.
However, in case you require some other format due to legacy code or no ability to change, the documentation states that type should be String, format should specify which format the date is in, and pattern should be provided as regex.
And this is exactly what I am doing in the above #Schema annotation.
However, when I go to https://editor.swagger.io/ and paste my .yaml file into it, the API generated for both my request model and my controller still contain incorrect formatting for birthdate and the example is not even taken into consideration:
Here is how it shows in my model:
As you can see, the format is still getting the format for OffsetDateTime and there is no example at all.
Same for my controller:
How do I make birthday show up as yyyyMMdd? For example, how to make it show as 19720226 in swagger editor?
I am using OpenApi/Swagger 3 in a Spring Boot application.
Related
We are exposing swagger-ui from our webserver using the Swashbuckle package working on top of Asp.Net Core. We are hitting an input validation issue for our Guid input fields.
The GUIDs we are pasting in, which are read from other parts of the system, are formatted as deb83f8a3edc4b78a2ece3321f81b58b, note the missing dashes. The input validation rejects this as it expects dashes in the format (so it accepts deb83f8a-3edc-4b78-a2ec-e3321f81b58b).
The swagger document that we serve has the parameter as type: string and format: uuid. It calls to some internal validationGuid call that have a reg-ex that forces the dashes. From the browser Console it seems like it is looking for a component called JsonSchema_string_uuid but is not finding it.
So my question is how can I extend swagger-ui to override the validation of specific parameter type/formats?
UPDATE:
I was made aware of the RFC that specifies a UUID as containing dashes and a workaround. However, I'm still interested in learning about ways to customize the validation of both custom formats and specifically uuid?
While the OpenAPI Specification and JSON Schema do not currently define format: uuid, RFC 4122 defines UUID as containing dashes, and some comments in the OpenAPI repository suggest that format: uuid is supposed to follow RFC 4122. This means your example without dashes is most likely not format: uuid.
Consider replacing format: uuid with pattern: '^[A-Fa-f0-9]{32}$'.
I have a Django Rest Framework serializer with a DateTimeField. By default it will deserialize date/time values using the iso-8601 format. However, iso-8601 doesn't require a timezone offset. I need the user to always provide some timezone offset information (or better said, validate agains rfc 3339, a subset of iso-8601).
The field allows you to set a custom list of input_formats, but since Python is unable to parse rfc 3339 formatted dates correctly (i.e. an offset with a colon between the hour and minute part is unsupported) I'm stuck.
The DateTimeField in Django Rest Framework is perfectly capable of parsing rfc 3339 datetime values thanks to it's use of django.utils.dateparse.parse_datetime (it's somewhat more lenient, but that's fine).
parse_datetime either returns a timezone aware datetime instance (with tzinfo zet to a fixed offset) or a naive datetime instance (no tzinfo).
Django Rest Framework's DateTimeField converts any given value to an aware datetime value if settings.USE_TZ is set or the field was given a value for the default_timezone argument, otherwise any value is made naive.
The enforce_timezone method of DateTimeField is responsible for making values aware/naive.
Knowing this, enforcing that parsed values must be timezone aware can be achieved by overriding enforce_timezone and raising a ValidationError if the parsed datetime value is naive:
from django.utils import timezone
class DateTimeFieldWithOffset(serializers.DateTimeField):
default_error_messages = {
'naive': 'Datetime value is missing a timezone offset.'
}
def enforce_timezone(self, value):
if timezone.is_naive(value):
self.fail('naive')
return super().enforce_timezone(value)
I am working on a Spring 3 project and I need to format a Long field for Turkish currency. The default Locale of the application is en_US. I used the #NumberFormat annotation as below:
#NumberFormat(style=NumberFormat.Style.CURRENCY)
public Long getBudgetLimit() {
return budgetLimit;
}
The annotation works and formats the form field in English locale. However I need to use Turkish locale for this field. Is there a way to set the locale of a single field or a page different than the application's locale?
Edit: I just found the answer myself. Use a custom editor in the controller as below:
NumberFormat numberFormat = NumberFormat.getNumberInstance(new Locale("tr","TR"));
dataBinder.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class,numberFormat, true));
and do not use the #NumberFormat annotation. For same reason it gave an error for me.
There are many ways but you could for example register a custom implementation of AnnotationFormatterFactory<NumberFormat> as a bean which would allow you to handle the formatting manually. This is documentented in the Spring documentation section 6.6. The example in the documentation even handles the use case of adjusting #NumberFormat's behavior.
I have a data entity that I use in two ways, I populate a table with some of its data when the page loads, and when you click a row of that column, I AJAX up the details of that item and display them in form fields. I'm using Spring-Roo generated REST endpoints on the server side, and Backbone.js on the client.
When the table loads, date fields have the format I expect, coming straight out of my MySQL database ("yyyy-MM-dd"). When I get my AJAX data, date fields come to me as Unix time values (e.g. "1323666000000").
I can convert that on the client side, but that's stupid. Any idea how I can get my json controller to not do this?
I've tried pushing those fields into my .java file and messing with the #DateTimeFormat annotation, but I can't see that makes any difference.
You can transform the date to any format you want for your JSON response.
In your case, you've been using the default JSON date transformer all the time for the java.util.Date type fields. This is basically what gets generated for you by the Spring Roo. Take a look and in your *_Roo_Json aspects and you will find smth. like this:
public java.lang.String PizzaOrder.toJson() {
return new JSONSerializer().exclude("*.class").serialize(this);
}
Such an implementation uses the flexjson.transformer.BasicDateTransformer class to transform the date for you. It is implemented like this:
public class BasicDateTransformer extends AbstractTransformer {
public void transform(Object object) {
getContext().write(String.valueOf(((Date) object).getTime()));
}
}
What you want is to use a different, more powerfull transformer. Luckily it comes with your Roo and it's called flexjson.transformer.DateTransformer. Now, in order to format your dates properly, just replace the default with the new transformer e.g. like this:
public java.lang.String PizzaOrder.toJson() {
return new JSONSerializer().exclude("*.class")
.transform(new DateTransformer("MM/dd/yyyy"), Date.class)
.serialize(this);
}
That's all :-)
Know that you may also apply different Date (and not only) transformations for different fields like this:
transform(new DateTransformer("MM/dd/yyyy"), "person.birthday")
For more info about the flexjson take a look at FLEXJSON project page.
I have a ruby model that contains a date attribue which I'd like to be able to pass in as a parameter in the format dd/MM/yyyy.
However, my sqlite3 db stores the data in yyyy-MM-dd format so when a date like 20/10/2010 gets passed in, it will not be read to the database.
I am using the Sinatra framework and using haml for the markup creation.
Do I need to write a helper that takes the date string and converts it to the correct format for the db? Or can I set a format type on the models attribute?
Thanks.
You shouldn't need to worry about the database's internal representation of the date; DataMapper is there to do that for you. You just need to make sure you are passing it a valid Date object.
Check out http://ruby-doc.org/core/classes/Date.html for methods available to the Date class. For your example:
require 'date'
mydate = '20/10/2010'
mydate_obj = Date::strptime(mydate, '%d/%m/%Y')
puts "#{mydate_obj}" # prints 2010-10-20
I don't know if this can help, some time ago I had the same problem: I was using Rack::Utils.escape_html(params[:datetime]) to escape html on user input and if I typed a date in a form field like this "25/02/2013" it would be sent to the DataMapper model like this: 16/02/2013 (with escaped html codes) so it was saving it the wrong way (day ended up being the hour or something similar).
Maybe you are also using "escape_html" method in an awkward way?