JSON Schema Validator Selecting Validators - json

My problem is how do I get the json-schema-validator library to actually validate a JSON response against the JSON Schema I have defined. My goal is to get "additionalProperties" and field type checking working. I.e. have the validation reject unknown fields and check that numerics don't contain strings etc.
Files, code and background information follow.
Schema Swagger 2.0 standard definition
Schema Students API Defintion
{
"swagger": "2.0",
"info": {
"title": "Students API",
"description": "Operations on Students",
"version": "1.0"
},
"basePath": "/v1/students",
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"paths": {
"/{UID}": {
"get": {
"tags": [
"students"
],
"summary": "Get information about a Students Member.",
"description": "Given an University ID, return information for the identified students member.",
"operationId": "getStudentsByUID",
"produces": [
"application/xml",
"application/json"
],
"parameters": [
{
"required": true,
"name": "UID",
"in": "path",
"type": "string"
}
],
"responses": {
"200": {
"description": "OK. The operation was successful.",
"schema": {
"$ref": "#/definitions/Students"
}
},
"204": {
"description": "No Content. No Students the UID"
},
"400": {
"description": "Bad Request"
},
"401": {
"description": "Not Authorised"
},
"405": {
"description": "Method Not Allowed"
},
"429": {
"description": "Too Many Requests"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"definitions": {
"Students": {
"type": "object",
"additionalProperties": false,
"properties": {
"Status": {
"$ref": "#/definitions/Status"
},
"Person": {
"type": "array",
"items": {
"$ref": "#/definitions/Person"
}
}
}
},
"Status": {
"type": "object",
"additionalProperties": false,
"properties": {
"StatusCode": {
"type": "integer"
},
"Reason": {
"type": "string"
}
},
"required": [
"StatusCode",
"Reason"
]
},
"Person": {
"type": "object",
"description": "Representation of a person record for a student",
"properties": {
"PersonIdentifiers": {
"type": "object",
"properties": {
"Identifier": {
"type": "array",
"items": {
"$ref": "#/definitions/Identifier"
}
}
}
},
"PersonNames": {
"$ref": "#/definitions/PersonNames"
},
"AcademicPlanDetails": {
"type": "object",
"properties": {
"AcademicPlanDetail": {
"type": "array",
"items": {
"$ref": "#/definitions/AcademicPlanDetail"
}
}
}
}
}
},
"Identifier": {
"type": "object",
"properties": {
"IdentifierType": {
"type": "string"
},
"IdentifierValue": {
"type": "string"
}
}
},
"PersonNames": {
"type": "object",
"properties": {
"FirstName": {
"type": "string"
},
"MiddleName": {
"type": "string"
},
"LastName": {
"type": "string"
},
"Title": {
"type": "string",
"enum": [
"Mr",
"Mrs",
"Ms",
"Master",
"Dr"
]
},
"NameSuffixes": {
"description": "Not applicable to all Persons",
"type": "string",
"enum": [
"Jr",
"CPA",
"Esq",
"Ph.D"
]
},
"FullName": {
"type": "string"
},
"PreferredName": {
"description": "Not applicable to all Persons",
"type": "string"
},
"LongName": {
"type": "string"
},
"AliasName": {
"description": "Not applicable to all Persons",
"type": "string"
},
"Pronunciation": {
"description": "Not applicable to all Persons",
"type": "string"
}
}
},
"AcademicPlanDetail": {
"type": "object",
"properties": {
"AcademicCareer": {
"type": "string"
},
"StudentCareerNumber": {
"type": "string"
},
"EffectiveDate": {
"type": "string"
},
"EffectiveSequence": {
"type": "string"
},
"AcademicProgram": {
"type": "string"
},
"AcademicProgramDescription": {
"type": "string"
},
"AcademicPlan": {
"type": "string"
},
"AcademicPlanDescription": {
"type": "string"
},
"AcademicSubPlan": {
"type": "string"
},
"AcademicSubPlanDescription": {
"type": "string"
},
"ProgramStatus": {
"type": "string"
},
"ProgramStatusDescription": {
"type": "string"
},
"ProgramAction": {
"type": "string"
},
"ProgramActionDescription": {
"type": "string"
},
"ProgramReason": {
"type": "string"
},
"ProgramReasonDescription": {
"type": "string"
},
"AdmittedTerm": {
"type": "string"
},
"ResearchStudentCandidateNumber": {
"type": "string"
}
}
}
},
"tags": [
{
"name": "api-metadata",
"description": "Information about the API including its terms of use"
},
{
"name": "students",
"description": "Operations on all types of University students"
}
]
}
Students Response Good Valid response message
{
"Status": {
"StatusCode": 200,
"Reason": "OK",
},
"Person": [
{
"PersonIdentifiers": {
"Identifier": [
{
"IdentifierType": "UniversityID",
"IdentifierValue": "12345678"
},
{
"IdentifierType": "EmailAddress",
"IdentifierValue": "JohnSmith#no.such.org"
},
{
"IdentifierType": "PositionNumber",
"IdentifierValue": "00006789"
}
]
},
"PersonNames": {
"PreferredName": "",
"FirstName": "Johnathon",
"MiddleName": "",
"LastName": "Smith",
"Title": "Dr",
"NameSuffixes": "",
"FullName": "Smith,Jonathon",
"LongName": "",
"AliasName": "",
"Pronunciation": ""
},
"AcademicPlanDetails": {
"AcademicPlanDetail": [
{
"AcademicCareer": "RSCH",
"StudentCareerNumber": "0",
"EffectiveDate": "2019-12-19",
"EffectiveSequence": "1",
"AcademicProgram": "9876",
"AcademicProgramDescription": "Arts & Social Sciences",
"AcademicPlan": "9876XPHD",
"AcademicPlanDescription": "School of Humanities and the Arts",
"AcademicSubPlan": "HUMAN",
"AcademicSubPlanDescription": "Humanities",
"ProgramStatus": "AC",
"ProgramStatusDescription": "Active",
"ProgramAction": "MATR",
"ProgramActionDescription": "Matriculate",
"ProgramReason": "ACTV",
"ProgramReasonDescription": "Activated Manually",
"AdmittedTerm": "1903",
"ResearchStudentCandidateNumber": "000000034567"
}
]
}
}
]
}
Students Response Bad Invalid response message. Includes unwanted aggregates, fields and wrong data types.
{
"Fred": {
"Freddy": "Kruger"
},
"Status": {
"StatusCode": "200",
"Reason": "OK",
"X-Event-Id": "12340818-5a7c-11ea-920e-0a2835080000-1",
"Unexpected": "Undefined additional propery"
},
"Person": [
{
"PersonIdentifiers": {
"Identifier": [
{
"IdentifierType": "UniversityID",
"IdentifierValue": "12345678"
},
{
"IdentifierType": "EmailAddress",
"IdentifierValue": "JohnSmith#no.such.org"
},
{
"IdentifierType": "PositionNumber",
"IdentifierValue": "00006789"
}
]
},
"PersonNames": {
"PreferredName": "",
"FirstName": "Johnathon",
"MiddleName": "",
"LastName": "Smith",
"Title": "Dr",
"NameSuffixes": "",
"FullName": "Smith,Jonathon",
"LongName": "",
"AliasName": "",
"Pronunciation": ""
},
"AcademicPlanDetails": {
"AcademicPlanDetail": [
{
"AcademicCareer": "RSCH",
"StudentCareerNumber": "0",
"EffectiveDate": "2019-12-19",
"EffectiveSequence": "1",
"AcademicProgram": "9876",
"AcademicProgramDescription": "Arts & Social Sciences",
"AcademicPlan": "9876XPHD",
"AcademicPlanDescription": "School of Humanities and the Arts",
"AcademicSubPlan": "HUMAN",
"AcademicSubPlanDescription": "Humanities",
"ProgramStatus": "AC",
"ProgramStatusDescription": "Active",
"ProgramAction": "MATR",
"ProgramActionDescription": "Matriculate",
"ProgramReason": "ACTV",
"ProgramReasonDescription": "Activated Manually",
"AdmittedTerm": "1903",
"ResearchStudentCandidateNumber": "000000034567"
}
]
}
}
]
}
Code JSON Schema and JSON Instance validation
package com.nsd;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
public class JsvCmd {
public static final String JSON_V4_SCHEMA_IDENTIFIER = "http://json-schema.org/draft-04/schema#";
public static final String JSON_SCHEMA_IDENTIFIER_ELEMENT = "$schema";
public static void main(String[] args) throws IOException, ProcessingException {
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
// Load the JSON Schema for Swagger 2.0 API definition
File swaggerSchemaFile = new File("/Users/syntegrity/Documents/AnuStuff/Swagger2.0.json");
JsonNode jsonNodeSwagger = JsonLoader.fromFile(swaggerSchemaFile);
JsonNode schemaIdentifierSwagger = jsonNodeSwagger.get(JSON_SCHEMA_IDENTIFIER_ELEMENT);
if (null != schemaIdentifierSwagger) {
System.out.println("Swagger Schema Type: " + schemaIdentifierSwagger.asText());
}
final JsonSchema jsonSchemaSwagger = factory.getJsonSchema(jsonNodeSwagger);
// Next load the schema we are interested in and validate it against the Swagger 2.0 API schema
File userSchemaFile = new File("/Users/syntegrity/Documents/AnuStuff/Students_V1_SO.json");
JsonNode jsonNodeUserSchema = JsonLoader.fromFile(userSchemaFile);
ProcessingReport userSchemaReport = jsonSchemaSwagger.validate(jsonNodeUserSchema, true);
if (!userSchemaReport.isSuccess()) {
System.out.println("UserSchema is invalid");
System.out.println(userSchemaReport);
return;
}
// To get the validators we want used happening add a $schema element that specifies IETF Draft-04
JsonNode schemaIdentifierUser = jsonNodeUserSchema.get(JSON_SCHEMA_IDENTIFIER_ELEMENT);
if (null == schemaIdentifierUser) {
((ObjectNode) jsonNodeUserSchema).put(JSON_SCHEMA_IDENTIFIER_ELEMENT, JSON_V4_SCHEMA_IDENTIFIER);
System.out.println("User Schema coerced to IETF Draft-04 for validation purposes");
} else {
// For what we want to do anything other than a $schema value of IETF Draft-04 is going
// to cause problems. NOTE: The Swagger 2.0 API schema does not allow $schema anyway
if (!JSON_V4_SCHEMA_IDENTIFIER.equals(schemaIdentifierUser.asText())) {
System.out.println("Schema Type: " + schemaIdentifierUser.asText() + " is not " + JSON_V4_SCHEMA_IDENTIFIER);
return;
}
}
JsonSchema jsonSchemaUser = factory.getJsonSchema(jsonNodeUserSchema);
// Finally validate the JSON data
File jsonDataFile = new File("/Users/syntegrity/Documents/AnuStuff/Students_Bad_SO.json");
JsonNode jsonNodeData = JsonLoader.fromFile(jsonDataFile);
ProcessingReport userDataReport = jsonSchemaUser.validate(jsonNodeData, true);
if (!userSchemaReport.isSuccess()) {
System.out.println(userDataReport);
} else {
System.out.println("Sweet");
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nsd</groupId>
<artifactId>jsvcmd</artifactId>
<version>1.0.0</version>
<name>JsonValidator</name>
<description>JSON Validator Command Line</description>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.atlassian.oai/swagger-request-validator -->
<dependency>
<groupId>com.github.fge</groupId>
<artifactId>json-schema-validator</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>
<artifactId>jackson-coreutils</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Run Results
Swagger Schema Type: http://json-schema.org/draft-04/schema#
User Schema coerced to IETF Draft-04 for validation purposes
Sweet
I was hoping to see the following errors rather than "Sweet"
Unwanted: [Fred]
Unwanted: [X-Event-Id]
Unwanted: [Unexpected]
"200" is not of type integer
Debugging
If I change "produces" to "producesx" in the Students Schema the I get the following output.
UserSchema is invalid
com.github.fge.jsonschema.core.report.ListProcessingReport: failure
--- BEGIN MESSAGES ---
error: object instance has properties which are not allowed by the schema: ["producesx"]
level: "error"
schema: {"loadingURI":"#","pointer":""}
instance: {"pointer":""}
domain: "validation"
keyword: "additionalProperties"
unwanted: ["producesx"]
--- END MESSAGES ---
So when I use the Swagger 2.0 Schema to validate my Students Schema after making it invalid I get an error message. Yay.
This is not the case when I try to use Students Schema to validate Students Response Bad.
After getting very frustrated I finally decide to use Java Debug to step into the json-schema-validator and json-schema-core libraries.
In the InstanceValidator.class, see screenshots below, I found that for the first jsonSchemaSwagger.validate(jsonNodeUserSchema, true); call there were three validators linked to the fullContext object whereas in the second jsonSchemaUser.validate(jsonNodeData, true); call there were no validators linked to the fullContext object. Which I'm pretty sure means that no validation will take place.
First Call
InstanceValidator.class
Three Validators AdditionalPropertiesValidator, RequiredKeywordValidator and DraftV4TypeValidator
Second Call
No Validators
Finally
And so finally to the question. What calls do I need to make to use the same set of Validators for my second validation call? I.e. how do a create a list of Validators and then get them executed against the JSON Instance data?

Related

Mapping request body fields in logic apps

We have configured common alert schema for alerts and we are using a ticketing software and whenever we receive alert it should create a ticket.
In the logic app I have to make Post API call for creation of ticket with following json object, some fields are hard coded values:
{
"subject": "",
"Id": "123456789", // Hard code value
"priority": "",
"email": "test#test.com", // Hard code value
"status": "Open" // Hard code value
}
Parse Json sample payload schema for Alert:
{
"data": {
"alertContext": {
},
},
"customProperties": null,
"essentials": {
"alertContextVersion": "123",
"alertId": "123",
"alertRule": "Test Alerts",
"description": "test",
"severity": "Sev4"
}
},
"schemaId": "test"
}
I have to map "subject and "priority" fields with alert json object "description" and "severity":
subject-->description
priority --> severity // sev0 =high ,sev1=medium, sev2 =low
How can I achieve this using logic app?
After Parse JSON You can directly map its objects in the compose connector with the required fields. Below is my logic app flow.
You can use the below Code view to reproduce the same in your Logic app
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"customProperties": null,
"data": {
"alertContext": {}
},
"essentials": {
"alertContextVersion": "123",
"alertId": "123",
"alertRule": "Test Alerts",
"description": "test",
"severity": "Sev4"
},
"schemaId": "test"
},
"runAfter": {},
"type": "Compose"
},
"Compose_2": {
"inputs": {
"Id": "123456789",
"email": "test#test.com",
"priority": "#{body('Parse_JSON')?['essentials']?['severity']}",
"status": "Open",
"subject": "#{body('Parse_JSON')?['essentials']?['description']}"
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Compose"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"customProperties": {},
"data": {
"properties": {
"alertContext": {
"properties": {},
"type": "object"
}
},
"type": "object"
},
"essentials": {
"properties": {
"alertContextVersion": {
"type": "string"
},
"alertId": {
"type": "string"
},
"alertRule": {
"type": "string"
},
"description": {
"type": "string"
},
"severity": {
"type": "string"
}
},
"type": "object"
},
"schemaId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}

JSON Schema Validation with REST-assured - assert values not in json schema

Is there a way how to assert that API response contains values which are NOT in JSON schema? (e.g.: "name": "Nick")
API response example (name is not specified in schema below):
{
"id": "390",
"name": "Nick",
"data": {
"leagueId": 35,
"homeTeam": "Norway",
"visitingTeam": "England",
}
}
JSON schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"data": {
"type": "object",
"properties": {
"leagueId": {
"type": "integer"
},
"homeTeam": {
"type": "string"
},
"visitingTeam": {
"type": "string"
}
},
"required": [
"leagueId",
"homeTeam",
"visitingTeam"
]
}
},
"required": [
"id",
"data"
]
}
Comparison code example:
#Test
public void givenUrl_whenValidatesResponseWithInstanceSettings_thenCorrect() {
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder()
.setValidationConfiguration(
ValidationConfiguration.newBuilder()
.setDefaultVersion(SchemaVersion.DRAFTV4).freeze())
.freeze();
get("/events?id=390").then().assertThat()
.body(matchesJsonSchemaInClasspath("event_0.json")
.using(jsonSchemaFactory));
}

Json parse is giving null values

I have a logic app which gets Address info using Bind Rest Api. I received a nested json object. When I tried to parse it, I'm getting null values in dynamix syntax box.
Below is the json object that I get, however when I use these as properties after parsing, they are marked as null:
{
"address": {
"addressLine": "1-11-252, Begumpet Road",
"adminDistrict": "TS",
"adminDistrict2": "Hyderabad",
"countryRegion": "India",
"formattedAddress": "1-11-252, Begumpet Road, Hyderabad, TS 500016",
"intersection": {
"baseStreet": "Begumpet Road",
"secondaryStreet1": "Chikoti Garden No-4 Road",
"intersectionType": "Near",
"displayName": "Begumpet Road and Chikoti Garden No-4 Road"
},
"locality": "Hyderabad",
"neighborhood": "Begumpet",
"postalCode": "500016",
"countryRegionIso2": "IN"
}
}
Based on your information, here's what I did:
Created a Logic App in the Azure portal
Selected the "When a HTTP request is received" trigger
Clicked "Use sample payload to generate schema" link and pasted your example data (SEE BELOW!)
Added a "Response" action
Defined the response's body to be:
{
"address": baseStreet
}
Where baseStreet is a reference to the baseStreet dynamic content.
The result:
IMPORTANT!
Please be advised that the Request Body JSON Schema is different than the payload:
{
"type": "object",
"properties": {
"address": {
"type": "object",
"properties": {
"addressLine": {
"type": "string"
},
"adminDistrict": {
"type": "string"
},
"adminDistrict2": {
"type": "string"
},
"countryRegion": {
"type": "string"
},
"formattedAddress": {
"type": "string"
},
"intersection": {
"type": "object",
"properties": {
"baseStreet": {
"type": "string"
},
"secondaryStreet1": {
"type": "string"
},
"intersectionType": {
"type": "string"
},
"displayName": {
"type": "string"
}
}
},
"locality": {
"type": "string"
},
"neighborhood": {
"type": "string"
},
"postalCode": {
"type": "string"
},
"countryRegionIso2": {
"type": "string"
}
}
}
}
}
When running with the Parse JSON step:

avro runtime exception not a map when return in Json format

i have a avro schema for UKRecord, which contain a list of CMRecord(also avro schemaed):
{
"namespace": "com.uhdyi.hi.avro",
"type": "record",
"name": "UKRecord",
"fields": [
{
"name": "coupon",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "cm",
"type": [
"null",
{
"type": "array",
"items": {
"type": "record",
"name": "CmRecord",
"fields": [
{
"name": "id",
"type": "string",
"default": ""
},
{
"name": "name",
"type": "string",
"default": ""
}
]
}
}
],
"default": null
}
]
}
in my java code, i create a UKRecord which has all fields populated correctly, eventually i need to return this object using a json based api, however it complained:
org.apache.avro.AvroRuntimeException: Not a map: {"type":"record","name":"CmRecord","namespace":"com.uhdyi.hi.avro","fields":[{"name":"id","type":"string","default":""},{"name":"name","type":"string","default":""}]}
the java code that write the object to json is :
ObjectWriter writer = ObjectMapper.writer();
if (obj != null) {
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "application/json; charset=UTF-8");
byte[] bytes = writer.writeValueAsBytes(obj); <-- failed here
...
}
obj is:
{"coupon": "c12345", "cm": [{"id": "1", "name": "name1"}, {"id": "2", "name": "name2"}]}
why do i get this error? please help!
Because you are using unions, Avro is uncertain how to interpret the JSON you are providing. Here's how you can change the JSON so Avro knows it's not null
{
"coupon": { "string": "c12345" },
"cm": { "array": [
{ "id": "1", "name": "name1" },
{ "id": "2", "name": "name2" }
]
}
}
I know, it's really annoying how Avro chose to handle nulls.

JSON.Net: Schema validates where it shouldn't when using anyOf

I'm trying to detect if the user specified a boolean as a string instead of a real boolean.
I'm testing commentsModule/enabled to see if the value is false, once with quotes and once without.
The online validator: http://json-schema-validator.herokuapp.com/ works correctly, and identifies the failure as "instance value (\"false\") not found in enum (possible values: [false])".
However, NewtonSoft Json (latest version) with exactly the same schema and json defines this as a valid json.
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"anyOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
}
}
}
(using oneOf gives the same result)
JSON:
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "my name",
"description": "this is decription.” ",
"channel": "tech",
"commentsModule": {
"CaptionFieldDoesntExist": "Comments",
"enabled": "false"
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": ""
}
Json.Net code (taken from the official site):
JsonSchema schema = JsonSchema.Parse(schemaJson);
JObject jsonToVerify = JObject.Parse(json);
IList<string> messages;
bool valid = jsonToVerify.IsValid(schema, out messages);
Thank you!
EDIT:
Json.Net doesn't support Json Schema v4, so the "definitions" references are ignored.
For example, in this case the "caption" is checked for minimal length of 1, and has 0, but Json.net passes validation:
JSON
{
"_id": {
"$oid": "530dfec1e4b0ee95f0f3ce11"
},
"pageId": 1234,
"pageType": "Show",
"name": "another name",
"description": "description ",
"channel": "tech",
"commentsModule": {
"caption": "",
"enabled": true
},
"localInstance": "com",
"productionYear": "2014",
"navbarCaptionLink": "",
"logoAd": "" }
Schema:
{
"$schema":"http://json-schema.org/draft-04/schema#",
"description": "pages json",
"type": "object",
"properties":
{
"name": {"type":"string"},
"description": {"type":"string"},
"channel": {"type":"string"},
"commentsModule":{
"type": "object",
"oneOf":[
{ "$ref": "#/definitions/commentsModuleDisabled" },
{ "$ref": "#/definitions/commentsModuleEnabled" }
]
}
},
"definitions":{
"commentsModuleDisabled":{
"required": [ "enabled" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ false ] }
}
},
"commentsModuleEnabled":{
"required": [ "enabled", "caption" ],
"properties": {
"enabled": { "type": "boolean", "enum": [ true ] },
"caption": { "type": "string", "minLength": 1 }
}
}
} }
the error from the online tool in this case talks about mismatches for both schemas and refers to the minimal length requirement:
"message" : "instance failed to match exactly one schema (matched 0 out of 2)"
... "message" : "string \"\" is too short (length: 0, required minimum: 1)",
Json.Net doesn't support Json Schema v4, only v3. That's why "anyOf" and "definitions" are not recognized and the validation passes.
Update:
Json.NET Schema has full support for Draft 4.