Skip to content

Instantly share code, notes, and snippets.

@mariosotil
Last active January 16, 2017 14:44
Show Gist options
  • Save mariosotil/e1219d4e946c643fe0e5 to your computer and use it in GitHub Desktop.
Save mariosotil/e1219d4e946c643fe0e5 to your computer and use it in GitHub Desktop.
To be injected as a singleton, it allows validate a Swagger 2.0 description resource
/* Copyright 2017 Mario Sotil
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package helper.json;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.google.inject.Singleton;
import java.io.IOException;
import java.net.URL;
import java.util.Optional;
import java.util.stream.StreamSupport;
@Singleton
public class SwaggerValidator {
public final String ERROR_MESSAGES_FIELD = "errorMessages";
public final String SWAGGER_JSON_SCHEMA_URL = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/schemas/v2.0/schema.json";
private final JsonSchema jsonSchema;
private final JsonSchemaFactory factory;
public SwaggerValidator() {
factory = JsonSchemaFactory.byDefault();
jsonSchema = getJsonSchema(SWAGGER_JSON_SCHEMA_URL);
}
/**
* Validates a JsonNode within last Swagger 2.0 schema
*
* @param jsonNode the JsonNode object to be validated
* @return On success, it will return and empty ArrayNode object. On error, it will have all the messages
* returned by the validator.
*/
public ArrayNode validate(JsonNode jsonNode) {
return Optional.of(jsonNode)
.map(this::validateWithinSwaggerSchema)
.map(this::getMessagesAsJsonArray)
.get();
}
private ArrayNode getMessagesAsJsonArray(ProcessingReport report) {
ArrayNode messages = Optional.of(new ObjectMapper())
.map(ObjectMapper::createObjectNode)
.map(node -> node.putArray(ERROR_MESSAGES_FIELD))
.get();
if (!report.isSuccess()) {
StreamSupport.stream(report.spliterator(), false)
.map(ProcessingMessage::asJson)
.forEach(messages::add);
}
return messages;
}
private ProcessingReport validateWithinSwaggerSchema(JsonNode jsonNode) {
ProcessingReport report;
try {
report = jsonSchema.validate(jsonNode);
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return report;
}
private JsonSchema getJsonSchema(String url) {
return Optional.of(url)
.map(this::getJsonNode)
.map(this::getJsonSchema)
.get();
}
private JsonSchema getJsonSchema(JsonNode jsonNodeSchema) {
JsonSchema jsonSchemaNode;
try {
jsonSchemaNode = factory.getJsonSchema(jsonNodeSchema);
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return jsonSchemaNode;
}
private JsonNode getJsonNode(String url) {
JsonNode jsonNodeSchema;
try {
jsonNodeSchema = JsonLoader.fromURL(new URL(url));
} catch (IOException e) {
throw new RuntimeException(e);
}
return jsonNodeSchema;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment