Commit e87194b3 authored by Andrey Goder's avatar Andrey Goder Committed by Andre Azevedo

Add JSON Schema Validator

Summary:
This is a validator for  JSON schema (http://json-schema.org/) that works on
folly::dynamic. Apparently there are no good open source ones for C++,
especially not if you want to use folly::dynamic. I am going to use this to
validate JSON configs.

It supports basically everything from the standard, except for fetching schemas
via http, and using id refs. It supports enough to check schemas against the
metaschema.

Currently you can define a schema that will crash on validation, if it's
infinitely self-recursive. See the unit test case that reproduces this.
Fixing this seems hard though, so I didn't bother. It would also probably
be slower for normal usage.

Test Plan: unit test

Reviewed By: lesha@fb.com

Subscribers: trunkagent, folly-diffs@, yfeldblum

FB internal diff: D1847657

Signature: t1:1847657:1425605163:635dc523aeda1b588c3634d0dc1a48d50a53db79
parent 88fb213f
......@@ -78,6 +78,7 @@ nobase_follyinclude_HEADERS = \
experimental/Singleton-inl.h \
experimental/TestUtil.h \
experimental/Select64.h \
experimental/JSONSchema.h \
FBString.h \
FBVector.h \
File.h \
......@@ -343,6 +344,7 @@ libfolly_la_SOURCES = \
experimental/Singleton.cpp \
experimental/TestUtil.cpp \
experimental/Select64.cpp \
experimental/JSONSchema.cpp \
wangle/acceptor/Acceptor.cpp \
wangle/acceptor/ConnectionManager.cpp \
wangle/acceptor/LoadShedConfiguration.cpp \
......
This diff is collapsed.
/*
* Copyright 2015 Facebook, Inc.
*
* 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.
*/
#pragma once
#include <folly/ExceptionWrapper.h>
#include <folly/dynamic.h>
#include <folly/Range.h>
/**
* Validation according to the draft v4 standard: http://json-schema.org/
*
* If your schema is invalid, then it won't validate anything. For example, if
* you set "type": "invalid_type" in your schema, then it won't check for any
* type, as if you had left that property out. If you want to make sure your
* schema is valid, you can optionally validate it first according to the
* metaschema.
*
* Limitations:
* - We don't support fetching schemas via HTTP.
* - We don't support remote $refs.
* - We don't support $ref via id (only by path).
* - We don't support UTF-8 for string lengths, i.e. we will count bytes for
* schemas that use minLength/maxLength.
*/
namespace folly {
namespace jsonschema {
/**
* Interface for a schema validator.
*/
struct Validator {
virtual ~Validator() = 0;
/**
* Check whether the given value passes the schema. Throws if it fails.
*/
virtual void validate(const dynamic& value) const = 0;
/**
* Check whether the given value passes the schema. Returns an
* exception_wrapper indicating success or what the failure was.
*/
virtual exception_wrapper try_validate(const dynamic& value) const
noexcept = 0;
};
/**
* Make a validator that can be used to check various json. Thread-safe.
*/
std::unique_ptr<Validator> makeValidator(const dynamic& schema);
/**
* Makes a validator for schemas. You should probably check your schema with
* this before you use makeValidator().
*/
Validator* makeSchemaValidator();
}
}
/*
* Copyright 2015 Facebook, Inc.
*
* 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.
*/
#include <folly/experimental/JSONSchema.h>
#include <folly/json.h>
#include <fstream>
#include <string>
/**
* A binary that supports testing against the official tests from:
* https://github.com/json-schema/JSON-Schema-Test-Suite
*
* Use it like:
* ./jsonschema_tester /path/to/test.json
*/
int main(int argc, char** argv) {
if (argc < 2) {
printf("Usage: %s <testfile> [testfile2]...\n", argv[0]);
return -1;
}
for (int i = 1; i < argc; ++i) {
printf("FILE: %s\n", argv[i]);
std::ifstream fin(argv[i]);
std::stringstream buffer;
buffer << fin.rdbuf();
const folly::dynamic d = folly::parseJson(buffer.str());
for (const auto& item : d) {
printf("TEST: %s\n", item["description"].c_str());
auto v = folly::jsonschema::makeValidator(item["schema"]);
for (const auto& t : item["tests"]) {
printf("\t%s... ", t["description"].c_str());
auto ew = v->try_validate(t["data"]);
bool had_error = !static_cast<bool>(ew);
if (had_error == t["valid"].asBool()) {
printf("passed\n");
} else {
printf("FAILED\n");
}
}
}
}
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment