json/schema: add additionaProperties tests

This commit is contained in:
Danny Robson 2018-07-12 15:56:03 +10:00
parent 8c222300ca
commit d48e36ffd5
17 changed files with 117 additions and 2 deletions

View File

@ -16,9 +16,12 @@
#include "combine.hpp" #include "combine.hpp"
#include "properties.hpp"
#include "../tree.hpp" #include "../tree.hpp"
#include "../../iterator.hpp" #include "../../iterator.hpp"
#include "../../cast.hpp"
using util::json::schema::constraint::combine; using util::json::schema::constraint::combine;
@ -38,6 +41,20 @@ combine::combine (::json::tree::node const &def)
} }
m_constraints.push_back (instantiate (key, *val)); m_constraints.push_back (instantiate (key, *val));
if (key == "additionalProperties") {
m_additional = util::cast::known<additional_properties> (m_constraints.back ().get ());
m_additional->use (m_properties);
m_additional->use (m_patterns);
} else if (key == "properties") {
m_properties = util::cast::known<properties> (m_constraints.back().get ());
if (m_additional)
m_additional->use (m_properties);
} else if (key == "patternProperties") {
m_patterns = util::cast::known<pattern_properties> (m_constraints.back ().get ());
if (m_additional)
m_additional->use (m_patterns);
}
} }
} }

View File

@ -17,6 +17,8 @@
#pragma once #pragma once
#include "base.hpp" #include "base.hpp"
#include "fwd.hpp"
#include "../tree.hpp" #include "../tree.hpp"
#include <memory> #include <memory>
@ -47,6 +49,10 @@ namespace util::json::schema::constraint {
std::string m_version; std::string m_version;
std::unique_ptr<::json::tree::node> m_default; std::unique_ptr<::json::tree::node> m_default;
properties *m_properties = nullptr;
pattern_properties *m_patterns = nullptr;
additional_properties *m_additional = nullptr;
std::vector<std::unique_ptr<base>> m_constraints; std::vector<std::unique_ptr<base>> m_constraints;
}; };
} }

View File

@ -67,6 +67,14 @@ properties::validate (output_iterator res, ::json::tree::node &target) const noe
} }
//-----------------------------------------------------------------------------
bool
properties::has (std::string const &key) const noexcept
{
return m_properties.cend () != m_properties.find (key);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::ostream& std::ostream&
properties::describe (std::ostream &os) const properties::describe (std::ostream &os) const
@ -121,6 +129,20 @@ pattern_properties::validate (output_iterator res,
} }
//-----------------------------------------------------------------------------
bool
pattern_properties::has (std::string const &key) const noexcept
{
return std::any_of (
m_patterns.begin (),
m_patterns.end (),
[&key] (auto const &i)
{
return std::regex_search (key, i.matcher);
});
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::ostream& std::ostream&
pattern_properties::describe (std::ostream &os) const pattern_properties::describe (std::ostream &os) const
@ -133,11 +155,38 @@ pattern_properties::describe (std::ostream &os) const
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
additional_properties::additional_properties (
::json::tree::node const &def,
properties *_properties,
pattern_properties *_patterns
)
: m_fallback (def)
, m_properties (_properties)
, m_patterns (_patterns)
{ ; }
//-----------------------------------------------------------------------------
additional_properties::additional_properties (::json::tree::node const &def): additional_properties::additional_properties (::json::tree::node const &def):
m_fallback (def) additional_properties (def, nullptr, nullptr)
{ } { }
//-----------------------------------------------------------------------------
void
additional_properties::use (properties *ptr)
{
m_properties = ptr;
}
//-----------------------------------------------------------------------------
void
additional_properties::use (pattern_properties *ptr)
{
m_patterns = ptr;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
additional_properties::output_iterator additional_properties::output_iterator
additional_properties::validate (output_iterator res, additional_properties::validate (output_iterator res,
@ -146,8 +195,15 @@ additional_properties::validate (output_iterator res,
if (!target.is_object ()) if (!target.is_object ())
return *res++ = { .rule = *this, .target = target }; return *res++ = { .rule = *this, .target = target };
for (auto &[key,val]: target.as_object ()) for (auto &[key,val]: target.as_object ()) {
// don't check properties that are handled elsewhere
if (m_patterns && m_patterns->has (key))
continue;
if (m_properties && m_properties->has (key))
continue;
res = m_fallback.validate (res, *val); res = m_fallback.validate (res, *val);
}
return res; return res;
} }

View File

@ -35,6 +35,8 @@ namespace util::json::schema::constraint {
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override; output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
std::ostream& describe (std::ostream&) const override; std::ostream& describe (std::ostream&) const override;
bool has (std::string const &key) const noexcept;
private: private:
std::map<std::string,combine> m_properties; std::map<std::string,combine> m_properties;
}; };
@ -47,6 +49,8 @@ namespace util::json::schema::constraint {
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override; output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
std::ostream& describe (std::ostream&) const override; std::ostream& describe (std::ostream&) const override;
bool has (std::string const &key) const noexcept;
private: private:
struct pattern_t { struct pattern_t {
std::string pattern; std::string pattern;
@ -65,6 +69,9 @@ namespace util::json::schema::constraint {
virtual ~additional_properties () = default; virtual ~additional_properties () = default;
void use (properties*);
void use (pattern_properties*);
output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override; output_iterator validate (output_iterator, ::json::tree::node &target) const noexcept override;
std::ostream& describe (std::ostream&) const override; std::ostream& describe (std::ostream&) const override;

View File

@ -0,0 +1 @@
{ "key": null }

View File

@ -0,0 +1,3 @@
{
"key": {}
}

View File

@ -0,0 +1 @@
{ "key": "value" }

View File

@ -0,0 +1,3 @@
{
"additionalProperties": { "type": "string" }
}

View File

@ -0,0 +1 @@
{ "int": "string" }

View File

@ -0,0 +1 @@
{ "bool": "string" }

View File

@ -0,0 +1 @@
{ "int": 0 }

View File

@ -0,0 +1 @@
{ "bool": true }

View File

@ -0,0 +1 @@
{ "key": "string" }

View File

@ -0,0 +1,5 @@
{
"int": 0,
"bool": true,
"key": "string"
}

View File

@ -0,0 +1,9 @@
{
"properties": {
"int": { "type": "integer" }
},
"patternProperties": {
"^bool": { "type": "boolean" }
},
"additionalProperties": { "type": "string" }
}