mirror of
https://github.com/tristanpenman/valijson.git
synced 2024-12-13 10:32:58 +01:00
Merge pull request #133 from rayvincent2/feature/add-urn-reference-support
Add support for urn document references
This commit is contained in:
commit
ad7dac75a5
@ -95,7 +95,8 @@ if(valijson_BUILD_TESTS)
|
||||
|
||||
set(TEST_SOURCES
|
||||
tests/test_adapter_comparison.cpp
|
||||
tests/test_fetch_document_callback.cpp
|
||||
tests/test_fetch_urn_document_callback.cpp
|
||||
tests/test_fetch_absolute_uri_document_callback.cpp
|
||||
tests/test_json_pointer.cpp
|
||||
tests/test_json11_adapter.cpp
|
||||
tests/test_jsoncpp_adapter.cpp
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
namespace valijson {
|
||||
@ -19,8 +20,20 @@ inline bool isUriAbsolute(const std::string &documentUri)
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder function to resolve a relative URI within a given scope
|
||||
*/
|
||||
* @brief Placeholder function to check whether a URI is a URN
|
||||
*
|
||||
* This function validates that the URI matches the RFC 8141 spec
|
||||
*/
|
||||
inline bool isUrn(const std::string &documentUri) {
|
||||
static const std::regex pattern(
|
||||
"^((urn)|(URN)):(?!urn:)([a-zA-Z0-9][a-zA-Z0-9-]{1,31})(:[-a-zA-Z0-9\\\\._~%!$&'()\\/*+,;=]+)+(\\?[-a-zA-Z0-9\\\\._~%!$&'()\\/*+,;:=]+){0,1}(#[-a-zA-Z0-9\\\\._~%!$&'()\\/*+,;:=]+){0,1}$");
|
||||
|
||||
return std::regex_match(documentUri, pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder function to resolve a relative URI within a given scope
|
||||
*/
|
||||
inline std::string resolveRelativeUri(
|
||||
const std::string &resolutionScope,
|
||||
const std::string &relativeUri)
|
||||
|
@ -200,7 +200,7 @@ private:
|
||||
{
|
||||
if (resolutionScope) {
|
||||
if (documentUri) {
|
||||
if (internal::uri::isUriAbsolute(*documentUri)) {
|
||||
if (internal::uri::isUriAbsolute(*documentUri) || internal::uri::isUrn(*documentUri)) {
|
||||
return *documentUri;
|
||||
} else {
|
||||
return internal::uri::resolveRelativeUri(*resolutionScope, *documentUri);
|
||||
@ -210,6 +210,8 @@ private:
|
||||
}
|
||||
} else if (documentUri && internal::uri::isUriAbsolute(*documentUri)) {
|
||||
return *documentUri;
|
||||
} else if (documentUri && internal::uri::isUrn(*documentUri)) {
|
||||
return *documentUri;
|
||||
} else {
|
||||
return opt::optional<std::string>();
|
||||
}
|
||||
@ -600,7 +602,7 @@ private:
|
||||
if ((itr = object.find("id")) != object.end() && itr->second.maybeString()) {
|
||||
const std::string id = itr->second.asString();
|
||||
rootSchema.setSubschemaId(&subschema, itr->second.asString());
|
||||
if (!currentScope || internal::uri::isUriAbsolute(id)) {
|
||||
if (!currentScope || internal::uri::isUriAbsolute(id) || internal::uri::isUrn(id)) {
|
||||
updatedScope = id;
|
||||
} else {
|
||||
updatedScope = internal::uri::resolveRelativeUri(*currentScope, id);
|
||||
@ -993,7 +995,7 @@ private:
|
||||
const std::string actualJsonPointer = sanitiseJsonPointer(
|
||||
internal::json_reference::getJsonReferencePointer(jsonRef));
|
||||
|
||||
if (documentUri && internal::uri::isUriAbsolute(*documentUri)) {
|
||||
if (documentUri && (internal::uri::isUriAbsolute(*documentUri) || internal::uri::isUrn(*documentUri))) {
|
||||
// Resolve reference against remote document
|
||||
if (!fetchDoc) {
|
||||
throwRuntimeError("Fetching of remote JSON References not enabled.");
|
||||
|
@ -12,12 +12,12 @@ using valijson::SchemaParser;
|
||||
using valijson::adapters::RapidJsonAdapter;
|
||||
using valijson::Validator;
|
||||
|
||||
class TestFetchDocumentCallback : public ::testing::Test
|
||||
class TestFetchAbsoluteUriDocumentCallback : public ::testing::Test
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
const rapidjson::Document * fetchDocument(const std::string &uri)
|
||||
const rapidjson::Document * fetchAbsoluteUriDocument(const std::string &uri)
|
||||
{
|
||||
EXPECT_STREQ("http://localhost:1234/", uri.c_str());
|
||||
|
||||
@ -43,12 +43,12 @@ const rapidjson::Document * fetchDocument(const std::string &uri)
|
||||
return fetchedRoot;
|
||||
}
|
||||
|
||||
void freeDocument(const rapidjson::Document *adapter)
|
||||
void freeAbsoluteUriDocument(const rapidjson::Document *adapter)
|
||||
{
|
||||
delete adapter;
|
||||
}
|
||||
|
||||
TEST_F(TestFetchDocumentCallback, Basics)
|
||||
TEST_F(TestFetchAbsoluteUriDocumentCallback, Basics)
|
||||
{
|
||||
// Define schema
|
||||
rapidjson::Document schemaDocument;
|
||||
@ -60,8 +60,8 @@ TEST_F(TestFetchDocumentCallback, Basics)
|
||||
// Parse schema document
|
||||
Schema schema;
|
||||
SchemaParser schemaParser;
|
||||
schemaParser.populateSchema(schemaDocumentAdapter, schema, fetchDocument,
|
||||
freeDocument);
|
||||
schemaParser.populateSchema(schemaDocumentAdapter, schema, fetchAbsoluteUriDocument,
|
||||
freeAbsoluteUriDocument);
|
||||
|
||||
// Test resulting schema with a valid document
|
||||
rapidjson::Document validDocument;
|
80
tests/test_fetch_urn_document_callback.cpp
Normal file
80
tests/test_fetch_urn_document_callback.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <valijson/adapters/rapidjson_adapter.hpp>
|
||||
|
||||
#include <valijson/schema.hpp>
|
||||
#include <valijson/schema_parser.hpp>
|
||||
#include <valijson/validator.hpp>
|
||||
|
||||
using valijson::Schema;
|
||||
using valijson::SchemaParser;
|
||||
using valijson::adapters::RapidJsonAdapter;
|
||||
using valijson::Validator;
|
||||
|
||||
class TestFetchUrnDocumentCallback : public ::testing::Test
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
const rapidjson::Document * fetchUrnDocument(const std::string &uri)
|
||||
{
|
||||
EXPECT_STREQ("urn:mvn:example.schema.common:status:1.1.0", uri.c_str());
|
||||
|
||||
rapidjson::Document *fetchedRoot = new rapidjson::Document();
|
||||
fetchedRoot->SetObject();
|
||||
|
||||
rapidjson::Value valueOfTypeAttribute;
|
||||
valueOfTypeAttribute.SetString("string", fetchedRoot->GetAllocator());
|
||||
|
||||
rapidjson::Value schemaOfTestProperty;
|
||||
schemaOfTestProperty.SetObject();
|
||||
schemaOfTestProperty.AddMember("type", valueOfTypeAttribute,
|
||||
fetchedRoot->GetAllocator());
|
||||
|
||||
rapidjson::Value propertiesConstraint;
|
||||
propertiesConstraint.SetObject();
|
||||
propertiesConstraint.AddMember("test", schemaOfTestProperty,
|
||||
fetchedRoot->GetAllocator());
|
||||
|
||||
fetchedRoot->AddMember("properties", propertiesConstraint,
|
||||
fetchedRoot->GetAllocator());
|
||||
|
||||
return fetchedRoot;
|
||||
}
|
||||
|
||||
void freeUrnDocument(const rapidjson::Document *adapter)
|
||||
{
|
||||
delete adapter;
|
||||
}
|
||||
|
||||
TEST_F(TestFetchUrnDocumentCallback, Basics)
|
||||
{
|
||||
// Define schema
|
||||
rapidjson::Document schemaDocument;
|
||||
RapidJsonAdapter schemaDocumentAdapter(schemaDocument);
|
||||
schemaDocument.SetObject();
|
||||
schemaDocument.AddMember("$ref", "urn:mvn:example.schema.common:status:1.1.0",
|
||||
schemaDocument.GetAllocator());
|
||||
|
||||
// Parse schema document
|
||||
Schema schema;
|
||||
SchemaParser schemaParser;
|
||||
schemaParser.populateSchema(schemaDocumentAdapter, schema, fetchUrnDocument,
|
||||
freeUrnDocument);
|
||||
|
||||
// Test resulting schema with a valid document
|
||||
rapidjson::Document validDocument;
|
||||
validDocument.SetObject();
|
||||
validDocument.AddMember("test", "valid", schemaDocument.GetAllocator());
|
||||
Validator validator;
|
||||
EXPECT_TRUE(validator.validate(schema, RapidJsonAdapter(validDocument),
|
||||
NULL));
|
||||
|
||||
// Test resulting schema with an invalid document
|
||||
rapidjson::Document invalidDocument;
|
||||
invalidDocument.SetObject();
|
||||
invalidDocument.AddMember("test", 123, schemaDocument.GetAllocator());
|
||||
EXPECT_FALSE(validator.validate(schema, RapidJsonAdapter(invalidDocument),
|
||||
NULL));
|
||||
}
|
Loading…
Reference in New Issue
Block a user