Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenAPIDeserializer add seam for converting JsonNode to Object #2094

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -260,9 +262,6 @@ public class OpenAPIDeserializer {
private static final String COOKIE_PARAMETER = "cookie";
private static final String PATH_PARAMETER = "path";
private static final String HEADER_PARAMETER = "header";
private static final Pattern RFC3339_DATE_TIME_PATTERN = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):" +
"(\\d{2}):(\\d{2})(\\.\\d+)?((Z)|([+-]\\d{2}:\\d{2}))$");
private static final Pattern RFC3339_DATE_PATTERN = Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$");
private static final String REFERENCE_SEPARATOR = "#/";

private static final int MAX_EXTENSION_ENTRIES = 20;
Expand Down Expand Up @@ -297,7 +296,7 @@ public SwaggerParseResult deserialize(JsonNode rootNode, String path, ParseOptio
public SwaggerParseResult deserialize(JsonNode rootNode, String path, ParseOptions options, boolean isOaiAuthor) {
basePath = path;
this.rootNode = rootNode;
rootMap = new ObjectMapper().convertValue(rootNode, Map.class);
rootMap = convertValue(rootNode, Map.class);
SwaggerParseResult result = new SwaggerParseResult();
try {
ParseResult rootParse = new ParseResult();
Expand All @@ -319,6 +318,13 @@ public SwaggerParseResult deserialize(JsonNode rootNode, String path, ParseOptio
return result;
}

protected <T> T convertValue(JsonNode fromValue, Class<T> toValueType) {
if(Object.class.equals(toValueType)) {
return Json.mapper().convertValue(fromValue, toValueType);
}
return new ObjectMapper().convertValue(fromValue, toValueType);
}

public OpenAPI parseRoot(JsonNode node, ParseResult result, String path) {
String location = "";
OpenAPI openAPI = new OpenAPI();
Expand Down Expand Up @@ -517,7 +523,7 @@ private Map<String, Object> tryDirectExtensions(ObjectNode node) {
Set<String> keys = getKeys(node);
for (String key : keys) {
if (key.startsWith("x-")) {
extensions.put(key, Json.mapper().convertValue(node.get(key), Object.class));
extensions.put(key, convertValue(node.get(key), Object.class));
}
}

Expand Down Expand Up @@ -3201,23 +3207,10 @@ private OffsetDateTime toDateTime(String dateString) {
* Returns null if this string can't be parsed as Date.
*/
private Date toDate(String dateString) {
Matcher matcher = RFC3339_DATE_PATTERN.matcher(dateString);

Date date = null;
if (matcher.matches()) {
String year = matcher.group(1);
String month = matcher.group(2);
String day = matcher.group(3);

try {
date =
new Calendar.Builder()
.setDate(Integer.parseInt(year), Integer.parseInt(month) - 1,
Integer.parseInt(day))
.build()
.getTime();
} catch (Exception ignore) {
}
try {
date = new Date(LocalDate.parse(dateString).atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());
} catch (Exception ignore) {
}

return date;
Expand Down Expand Up @@ -4251,7 +4244,7 @@ public Schema getJsonSchema(JsonNode jsonNode, String location, ParseResult resu
for (String key : schemaKeys) {
validateReservedKeywords(specKeys, key, location, result);
if (!specKeys.get("SCHEMA_KEYS").contains(key) && !key.startsWith("x-")) {
extensions.put(key, Json.mapper().convertValue(node.get(key), Object.class));
extensions.put(key, convertValue(node.get(key), Object.class));
schema.setExtensions(extensions);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.swagger.v3.parser.test;

import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -25,13 +26,15 @@
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

public class OpenAPIV31ParserSchemaTest {
protected int serverPort = getDynamicPort();
protected WireMockServer wireMockServer;

private static SwaggerParseResult readLocation(String pathname, ParseOptions p) {
return new OpenAPIV3Parser().readLocation(new File(pathname).getAbsoluteFile().toURI().toString(), null, p);
}

private static int getDynamicPort() {
return new Random().ints(10000, 20000).findFirst().getAsInt();
}
Expand Down Expand Up @@ -167,54 +170,54 @@ private void tearDownWireMockServer() {
public void test$idUrlExternal() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$id-uri-external/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$id-uri-external/root.json", p);
compare("$id-uri-external", swaggerParseResult);
}

@Test
public void test$idUrlEnclosing() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$id-uri-enclosing/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$id-uri-enclosing/root.json", p);
compare("$id-uri-enclosing", swaggerParseResult);
}

@Test
public void test$idUrlDirect() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$id-uri-direct/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$id-uri-direct/root.json", p);
compare("$id-uri-direct", swaggerParseResult);
}
@Test
public void test$idUrlUnresolvable() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$id-unresolvable/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$id-unresolvable/root.json", p);
compare("$id-unresolvable", swaggerParseResult);
}

@Test
public void testAnchorExt() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$anchor-external/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$anchor-external/root.json", p);
compare("$anchor-external", swaggerParseResult);
}

@Test
public void testAnchorInt() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$anchor-internal/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$anchor-internal/root.json", p);
compare("$anchor-internal", swaggerParseResult);
}

@Test
public void testAnchorUnresolve() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(new File("src/test/resources/3.1.0/dereference/schema/$anchor-not-found/root.json").getAbsolutePath(), null, p);
SwaggerParseResult swaggerParseResult = readLocation("src/test/resources/3.1.0/dereference/schema/$anchor-not-found/root.json", p);
compare("$anchor-not-found", swaggerParseResult);
}

Expand All @@ -223,7 +226,7 @@ public void compare(String dir, SwaggerParseResult result) throws Exception {
ObjectMapper mapper = Json31.mapper().copy();
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
String actual = mapper.writer(new DefaultPrettyPrinter()).writeValueAsString(result.getOpenAPI());
String actual = mapper.writer(new DefaultPrettyPrinter().withObjectIndenter(new DefaultIndenter().withLinefeed("\n"))).writeValueAsString(result.getOpenAPI());
org.testng.Assert.assertEquals(actual,
FileUtils.readFileToString(new File("src/test/resources/3.1.0/dereference/schema/" + dir + "/dereferenced.json")));
}
Expand Down