fix: ExampleGenerator correctly produces YYYY-MM-dd format for date with examples (#17495)

When an example was specified for a property with the `date` format, it's example would be generated to something like `2024-01-01T00:00:00.000+00:00` or `Sat Jan 30 01:00:00 CET 2021`.

It's because the resolved type for a Date example is a DateSchema, and a DateSchema uses `java.util.Date` to represents the Date. Which gets printed using .toString() not in the YYYY-MM-dd format.

Fixes #17494 #15342
This commit is contained in:
Alexis Couvreur
2024-01-09 22:27:10 -05:00
committed by GitHub
parent e69c5269d5
commit 9b62b9bb05
3 changed files with 58 additions and 0 deletions
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
public class ExampleGenerator {
@@ -36,6 +37,8 @@ public class ExampleGenerator {
private static final String MIME_TYPE_JSON = "application/json";
private static final String MIME_TYPE_XML = "application/xml";
protected final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
private static final String EXAMPLE = "example";
private static final String CONTENT_TYPE = "contentType";
private static final String GENERATED_CONTENT_TYPE = "generatedContentType";
@@ -54,6 +57,7 @@ public class ExampleGenerator {
this.openAPI = openAPI;
// use a fixed seed to make the "random" numbers reproducible.
this.random = new Random("ExampleGenerator".hashCode());
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public List<Map<String, String>> generateFromResponseSchema(String statusCode, Schema responseSchema, Set<String> producesInfo) {
@@ -231,6 +235,11 @@ public class ExampleGenerator {
LOGGER.debug("Resolving example for property {}...", property);
if (property.getExample() != null) {
LOGGER.debug("Example set in openapi spec, returning example: '{}'", property.getExample().toString());
// When a property is of type Date, we want to ensure that we're returning a formatted Date.
// And not returning the Date object directly.
if (property.getExample() instanceof Date) {
return DATE_FORMAT.format(property.getExample());
}
return property.getExample();
} else if (ModelUtils.isBooleanSchema(property)) {
Object defaultValue = property.getDefault();
@@ -39,6 +39,35 @@ public class ExampleGeneratorTest {
assertEquals("200", examples.get(0).get("statusCode"));
}
@Test
public void generateFromResponseSchemaWithDateFormat() {
OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/example_generator_test.yaml");
new InlineModelResolver().flatten(openAPI);
ExampleGenerator exampleGenerator = new ExampleGenerator(openAPI.getComponents().getSchemas(), openAPI);
Set<String> mediaTypeKeys = new TreeSet<>();
mediaTypeKeys.add("application/json");
List<Map<String, String>> examples = exampleGenerator.generateFromResponseSchema(
"200",
openAPI
.getPaths()
.get("/generate_from_response_schema_with_date_format")
.getGet()
.getResponses()
.get("200")
.getContent()
.get("application/json")
.getSchema(),
mediaTypeKeys
);
assertEquals(1, examples.size());
assertEquals("application/json", examples.get(0).get("contentType"));
assertEquals(String.format(Locale.ROOT, "{%n \"date_with_example\" : \"2024-01-01\",%n \"date_without_example\" : \"2000-01-23\"%n}"), examples.get(0).get("example"));
assertEquals("200", examples.get(0).get("statusCode"));
}
@Test
public void generateFromResponseSchemaWithNoExample() {
OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/example_generator_test.yaml");
@@ -26,6 +26,16 @@ paths:
schema:
type: string
example: primitive type example value
/generate_from_response_schema_with_date_format:
get:
operationId: generateFromResponseSchemaWithDateFormat
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/DateSchema'
/generate_from_response_schema_with_array_of_model:
get:
operationId: generateFromResponseSchemaWithArrayOfModel
@@ -93,6 +103,16 @@ paths:
$ref: '#/components/schemas/ExampleOneOfSchema'
components:
schemas:
DateSchema:
type: object
properties:
date_with_example:
type: string
format: date
example: 2024-01-01
date_without_example:
type: string
format: date
StringSchema:
type: string
example: string schema example value