gregsdennis / json-everything Goto Github PK
View Code? Open in Web Editor NEWSystem.Text.Json-based support for all of your JSON needs.
Home Page: https://json-everything.net/
License: MIT License
System.Text.Json-based support for all of your JSON needs.
Home Page: https://json-everything.net/
License: MIT License
Environment
Describe the bug
Discovered from #85.
To Reproduce
public class TreeNode
{
public string Value { get; set; }
[JsonPropertyName("left")] // these are required for the error
public TreeNodeMetaData Left { get; set; }
[JsonPropertyName("right")]
public TreeNodeMetaData Right { get; set; }
}
public class TreeNodeMetaData
{
public TreeNode Node { get; set; }
public int Position { get; set; }
}
Expected behavior
Schema is generated.
JsonLogic is a math/boolean logic DSL that's represented in JSON.
Environment
Describe alternatives you've considered
Now, when I has a class below:
public class Test
{
public string Name { get; set; }
public string Name2 { get; set; }
public int IntValue { get; set; }
public int IntValue2 { get; set; }
public Guid GuidValue { get; set; }
}
run as:
var mySchema = new JsonSchemaBuilder().FromType<Test>().Build();
Console.WriteLine(JsonSerializer.Serialize(mySchema,
new JsonSerializerOptions(JsonSerializerDefaults.General)
{
WriteIndented = true
}));
we get result:
{
"type": "object",
"properties": {
"EnumValue": {
"enum": [
"A",
"B"
]
},
"GuidValue": {
"type": "object",
"properties": {}
},
"IntValue": {
"$ref": "#/$defs/integer" // what I expected this line should be : "type":"integer"
},
"IntValue2": {
"$ref": "#/$defs/integer" // what I expected this line should be : "type":"integer"
},
"Name": {
"$ref": "#/$defs/string" // what I expected this line should be : "type":"string"
},
"Name2": {
"$ref": "#/$defs/string" // what I expected this line should be : "type":"string"
}
},
"$defs": {
"integer": {
"type": "integer"
},
"string": {
"type": "string"
}
}
}
$defs
seems unnecessary for Primitive Types such as string
, integer
, boolean
.
Environment
I'm using the validation like the code below:
public bool IsValid(string data, out string result)
{
if (!string.IsNullOrWhiteSpace(Schema))
{
var doc = JsonDocument.Parse(data);
JsonSchema schema = JsonSchema.FromText(Schema);
var validationResult = schema.Validate(doc.RootElement);
result = validationResult.IsValid ? "Validation Succeeded." : validationResult.Message;
return validationResult.IsValid;
}
else
{
throw new Exception("Schema not set");
}
}
However, validationResult.Message
doesn't contain anything (null) even if the json input is invalid.
Whereas, Json.NET's Schema validator contains at least some message
e.g.
Integer -1 is less than minimum value of 0. Line 4, position 12.
Is it possible to get the reason of the schema validation error like the one above?
To replicate, I've created a dummy solution here:
https://github.com/whatevergeek/JsonSchemaDemo
You may run the unit tests to replicate the issue.
Hello,
as requested this ticket is a follow up-to #96.
Environment
Can this library make doing something simpler?
With the introduction of Refiners, we now have a clean way to dynamically modify the SchemaGeneratorContext.
But with the current design of the cache and optimization phase, we can't modify "individual properties".
Describe alternatives you've considered
Replace tracking of type/attribute set with tracking of type/intent set.
Additional context
Let's consider this class:
public class MyClass
{
public string Name { get; set; }
public string Description { get; set; }
}
and the associated refiner, which adds an intent to the Name property:
public class MyClassRefiner : ISchemaRefiner
{
private static Dictionary<string, List<ISchemaKeywordIntent>> customIntents = new()
{
{ "Name", new() { new MaxLengthIntent(42) } }
};
public void Run(SchemaGeneratorContext context)
{
foreach (var property in context.Intents.Where(i => i is PropertiesIntent).SelectMany(i => (i as PropertiesIntent).Properties))
{
if(customIntents.TryGetValue(property.Key, out var propertyCustomIntents))
{
foreach (var customIntentToAdd in propertyCustomIntents)
{
property.Value.Intents.Add(customIntentToAdd);
}
}
}
}
public bool ShouldRun(SchemaGeneratorContext context)
{
return context.Type.Equals(typeof(MyClass));
}
}
Now let's build and serialize the schema for our type :
var schema = new JsonSchemaBuilder().FromType<MyClass>(new ()
{
Refiners = new(){ new MyClassRefiner() }
}).Build();
Console.WriteLine(JsonSerializer.Serialize(schema, new JsonSerializerOptions { WriteIndented = true }));
We can see in the generated schema that both string properties have been considered equal, hence have been "grouped" by the optimizer :
{
"type": "object",
"properties": {
"Description": {
"$ref": "#/$defs/string"
},
"Name": {
"$ref": "#/$defs/string"
}
},
"$defs": {
"string": {
"type": "string",
"maxLength": 42
}
}
}
What we expect is having only the Name property impacted by the added intent, like so:
{
"type": "object",
"properties": {
"Description": {
"type": "string"
},
"Name": {
"type": "string",
"maxLength": 42
}
}
}
I'm creating a JsonSchema dynamically by code.
How can I add a property to the existing properties?
The following will produce a JsonSchema with only a "p2" property:
var b = new JsonSchemaBuilder();
b = b.Properties(("p1", new JsonSchemaBuilder().Type(SchemaValueType.Object)));
b = b.Properties(("p2", new JsonSchemaBuilder().Type(SchemaValueType.Object)));
Describe the bug
Schema with draft 07 doesn't recognized the Schema draft 04.
Probably should be considered as new feature. In our validators we want to enforce the use the draft 07 and we don't want to support other drafts at the moment. Some additional information should be provided from thte JsonSchema object.
Expected behavior
Schema draft 04 should be recognized from Schema draft 07.
To Reproduce
using Manatee.Json;
using Manatee.Json.Schema;
using System;
using System.Text.Json;
using JsonEverythingSchema = Json.Schema.JsonSchema;
using ManateeJsonSchema = Manatee.Json.Schema.JsonSchema;
using ManateeJsonSerializer = Manatee.Json.Serialization.JsonSerializer;
namespace jsonschema
{
class Program
{
private static readonly ManateeJsonSerializer _serializer = new ManateeJsonSerializer();
static void Main(string[] args)
{
var json = "{}";
Console.WriteLine($"Validate {json} against {MyInvalidSchema}");
ManateeValidation(MyInvalidSchema, json); // Expected Schema Invalid
JsonEverythingValidation(MyInvalidSchema, json); // Expected Schema Invalid
}
private static void JsonEverythingValidation(string schema, string json)
{
var jsSchema = JsonDocument.Parse(schema).RootElement;
var schemaValidationResult = Json.Schema.MetaSchemas.Draft7.Validate(jsSchema);
if (!schemaValidationResult.IsValid)
{
Console.Error.WriteLine($"JsonEverything: Schema is invalid - reason {schemaValidationResult.Message}");
return;
}
var jsonSchema = JsonEverythingSchema.FromText(schema);
var validationResult = jsonSchema.Validate(JsonDocument.Parse(json).RootElement);
Console.WriteLine($"JsonEverything: Valid {validationResult.IsValid} - {validationResult.Message}");
}
private static void ManateeValidation(string schema, string json)
{
var jsonSchema = _serializer.Deserialize<ManateeJsonSchema>(JsonValue.Parse(schema));
var schemaResult = jsonSchema.ValidateSchema();
if (!schemaResult.IsValid)
{
Console.Error.WriteLine("Manatee: Schema is invalid");
return;
}
if ((schemaResult.SupportedVersions & JsonSchemaVersion.Draft07) == 0)
{
Console.Error.WriteLine("Manatee: Schema is invalid expected draft 07");
return;
}
var validationResult = jsonSchema.Validate(JsonValue.Parse(json));
Console.WriteLine($"Manatee: Valid {validationResult.IsValid} - {validationResult.AdditionalInfo.ToString()}");
}
private static readonly string MyInvalidSchema = "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\"\n}\n";
}
}
Describe the bug
Can not asJsonElement a specific valid JSon
To Reproduce
"{\"BazaarItem\":{\"Amount\":99,\"BazaarItemId\":0,\"DateStart\":\"2020-12-18T23:44:46.0893914Z\",\"Duration\":3600,\"IsPackage\":false,\"ItemInstanceId\":\"9abf1cd6-25e4-41e5-9353-4be2e80bbab3\",\"MedalUsed\":false,\"Price\":80,\"SellerId\":1},\"ItemInstance\":{\"Amount\":99,\"BoundCharacterId\":null,\"CharacterId\":0,\"Design\":0,\"DurabilityPoint\":0,\"ItemDeleteTime\":null,\"ItemVNum\":0,\"Upgrade\":0,\"Rare\":0,\"Id\":\"9abf1cd6-25e4-41e5-9353-4be2e80bbab3\"},\"SellerName\":\"test\"}".AsJsonElement()
"'B' is invalid after a single JSON value. Expected end of data. LineNumber: 0 | BytePositionInLine: 3."
Expected behavior
I think this should return a valid JsonElement.
Desktop (please complete the following information):
I have a schema that was partly described as -
schema = new JsonSchemaBuilder()
.Schema("https://json-schema.org/draft/2019-09/schema")
.Id("http://acme.com/components/purchaseorder")
.Type(SchemaValueType.Object)
.Properties(
...,
(
"DateRequested", new JsonSchemaBuilder()
.Format(new Format("date-time"))
),...
and validated as -
ValidationOptions options = new ValidationOptions();
options.ValidateAs = Draft.Draft201909;
options.OutputFormat = OutputFormat.Detailed;
options.ValidateMetaSchema = true;
var res = schema.Validate(sbMessageBodyJson, options);
The above returns TRUE;
What I have since realised is that DateRequested=="1/1/0001 12:00:00 AM"
, the datetime formats provided by way of new Format("date-time")
are as defined in Formats.cs and the latter should not match the former. The validation should have returned FALSE;
It has been mentioned in the documentation that (paraphrasing) "Format should be an annotation that can provide validation so long as that validation may be configured on and off", and I am aware of this now closed issue, but I am confused as to what it all means.
Can I validate using a Format and, if so, am I doing it correctly?
I am currently using your library which work perfectly.
But I have some issues with dynamically modify the childrens properties.
Let me explain, I have two solutions that work, but I can't do everything I want.
I use this to generate the skeleton of an object :
JsonSchemaBuilder jschemaParent = new JsonSchemaBuilder().FromType<TEntity>();
This is exactly what I want and work perfectly.
After that I want to be able to modify the childrens properties, and for that the only solution that I found is something like that :
IJsonSchemaKeyword proprietes = ((Json.Schema.JsonSchema)jschemaParent).Keywords.First(c => c is PropertiesKeyword);
Dictionary<string, Json.Schema.JsonSchema> props = new Dictionary<string, Json.Schema.JsonSchema>();
foreach (var property in ((PropertiesKeyword)proprietes).Properties)
{
JsonSchemaBuilder jsonBuilder = new JsonSchemaBuilder();
foreach (IJsonSchemaKeyword keyword in property.Value.Keywords)
jsonBuilder.Add(keyword);
if (property.Key == "Numero")
jsonBuilder.ReadOnly(true);
props.Add(property.Key, jsonBuilder);
}
jschemaParent.Properties(props);
It works but I have to reimplement each property one by one, by getting each IJsonSchemaKeyword and then adding what I need.
Am I missing something, would there be no way to get a JsonSchemaBuilder from a JsonSchema to do it more easily ?
As the first solution I generate the skeleton of an object :
var context = SchemaGenerationContextCache.Get(typeof(TEntity), null);
This also works perfectly. I then created custom Intents to modify children properties :
PropertiesIntent properties = (PropertiesIntent)context.Intents.First(c => c is PropertiesIntent);
foreach (var propriete in properties.Properties)
{
if (propriete.Key == "Numero")
propriete.Value.Intents.Add(new ReadOnlyIntent(true));
}
The problem with this solution is that if the object contains the same type of property several times, it will add the ISchemaKeywordIntent on each property.
For this example, if my object contains two strings, the code above will add two readonly on each strings, but I only want to have it on the property 'Numero' and not the other one.
What am I doing wrong with this solution, how I could avoid duplications of ISchemaKeywordIntent for each property of the same type ?
For any solution I want to generate the skeleton of an object, and then modify children properties, because I have some complex objects, and then modify children properties.
Am I missing something, would there be a simpler solution to do that ?
Thanks in advance and sorry if my english is bad !
The next version is due out within a week or so. Probably a good idea to start development.
Firstly, thank you for such an awesome library and excellent documentation.
I installed it yesterday and am experimenting with adding a reference to a schema using the fluent approach (it would also be good to include a more fully fleshed out example on https://gregsdennis.github.io/json-everything/usage/schema/references.html that uses the fluent approach).
I think I have it right but it would be really good to see the generated schema as JSON. Could you override JsonSchema.toString() so that it outputs something that JsonSchema.FromText(content) could load?
Environment
Describe the bug
In some cases, the schema validation erroneously attempts to fetch the directory containing a schema as a schema itself. It seems to happen when we have one schema referring to another with a relative URI, and the second schema has internal references (i.e. "#/definitions/...
).
To Reproduce
var schema1Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""$id"": ""schema1.json"",
""definitions"": {
""myDef"": {
""properties"": {
""abc"": { ""type"": ""string"" }
}
}
},
""$ref"": ""#/definitions/myDef""
}";
var schema2Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""$id"": ""schema2.json"",
""$ref"": ""schema1.json""
}";
var jsonStr = @"{ ""abc"": ""s"" }";
var schema1 = JsonSerializer.Deserialize<JsonSchema>(schema1Str);
var schema2 = JsonSerializer.Deserialize<JsonSchema>(schema2Str);
var json = JsonDocument.Parse(jsonStr).RootElement;
var uri1 = new Uri("http://first.com/schema1.json");
var uri2 = new Uri("http://first.com/schema2.json");
var firstBaseUri = new Uri("http://first.com");
var map = new Dictionary<Uri, JsonSchema>
{
{ uri1, schema1 },
{ uri2, schema2 },
};
var options = new ValidationOptions
{
OutputFormat = OutputFormat.Verbose,
DefaultBaseUri = firstBaseUri,
SchemaRegistry =
{
Fetch = uri =>
{
Console.WriteLine("Fetching {0}", uri);
// return map.TryGetValue(uri, out var ret) ? ret : null;
return map[uri];
}
}
};
var validation = schema2.Validate(json, options);
Console.WriteLine("Validation: {0}", JsonSerializer.Serialize(validation));
Prints
Fetching http://first.com/schema1.json
Fetching http://first.com/
Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key 'http://first.com/' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at test3.Program.<>c__DisplayClass0_0.<Main>b__0(Uri uri) in /tmp/test_jsonschema/Program.cs:line 56
at Json.Schema.SchemaRegistry.Get(Uri uri, String anchor) in /git/json-everything/JsonSchema/SchemaRegistry.cs:line 115
at Json.Schema.RefKeyword.Validate(ValidationContext context) in /git/json-everything/JsonSchema/RefKeyword.cs:line 68
at Json.Schema.JsonSchema.ValidateSubschema(ValidationContext context) in /git/json-everything/JsonSchema/JsonSchema.cs:line 213
at Json.Schema.RefKeyword.Validate(ValidationContext context) in /git/json-everything/JsonSchema/RefKeyword.cs:line 110
at Json.Schema.JsonSchema.ValidateSubschema(ValidationContext context) in /git/json-everything/JsonSchema/JsonSchema.cs:line 213
at Json.Schema.JsonSchema.Validate(JsonElement root, ValidationOptions options) in /git/json-everything/JsonSchema/JsonSchema.cs:line 119
at test3.Program.Main(String[] args) in /tmp/test_jsonschema/Program.cs:line 60
Expected behavior
The URL http://first.com/
should never be fetched. This is a regression from version 1.8.0, which displays the correct behaviour.
A library that can compare two JSON documents and report on their differences.
Describe the functionality that isn't covered by this suite
System.Text.Json misses TypeConverter support, custom enum serialization out of the box and other small things.
Describe alternatives you've considered
There is a library Macross Json which provides such small utility classes.
It would be nice to have everything in one place.
Environment
Describe the bug
JsonSchema.GetHashCode
isn't consistent on field re-ordering. All the following schemas compare equal but have different hash-codes:
var schema1Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""required"": [
""a"",
""b""
],
""properties"": {
""a"": { ""const"": ""a"" },
""b"": { ""const"": ""b"" }
}
}";
var schema2Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""required"": [
""b"",
""a""
],
""properties"": {
""a"": { ""const"": ""a"" },
""b"": { ""const"": ""b"" }
}
}";
var schema3Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""required"": [
""a"",
""b""
],
""properties"": {
""b"": { ""const"": ""b"" },
""a"": { ""const"": ""a"" }
}
}";
var schema4Str = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""properties"": {
""a"": { ""const"": ""a"" },
""b"": { ""const"": ""b"" }
},
""required"": [
""a"",
""b""
]
}";
var schema1 = JsonSerializer.Deserialize<JsonSchema>(schema1Str);
var schema2 = JsonSerializer.Deserialize<JsonSchema>(schema2Str);
var schema3 = JsonSerializer.Deserialize<JsonSchema>(schema3Str);
var schema4 = JsonSerializer.Deserialize<JsonSchema>(schema4Str);
Console.WriteLine("{0}, {1}, {2}", schema1.Equals(schema2), schema1.GetHashCode(), schema2.GetHashCode());
Console.WriteLine("{0}, {1}, {2}", schema1.Equals(schema3), schema1.GetHashCode(), schema3.GetHashCode());
Console.WriteLine("{0}, {1}, {2}", schema1.Equals(schema4), schema1.GetHashCode(), schema4.GetHashCode());
It seems that Json.Pointer.EnumerableExtensions.GetCollectionHashCode
doesn't sort the enumerable, and neither do the callers.
Jsonnet is a templating language for creating JSON data.
I Have this model
public class BaseData
{
[Required]
[MinLength(10)]
public string ActionSource { get; set; }
}
and this is my code
Json.Schema.JsonSchema schema = new JsonSchemaBuilder().FromType<BaseData>().Build();
ValidationOptions options = new ValidationOptions();
options.OutputFormat = OutputFormat.Basic;
var validate = schema.Validate(JsonDocument.Parse(bodyString).RootElement, options);
the problem is validate.isvalid always returns true when ActionSource in json or not
Describe the bug
JsonSchema.FromFile
assigns BaseUri
of the result in a way that produces URI which different resource by not properly handling characters which should be escaped.
json-everything/JsonSchema/JsonSchema.cs
Line 64 in 6f99f55
To Reproduce
Place a schema on a path which has a character which should be escaped.
This is particularly visible if #
character is present, the part of path after #
is parsed as Uri.Fragment
which is not part of a file path when Uri.LocalPath
(and possibly other properties) is queried.
See https://dotnetfiddle.net/wrWwsw.
Expected behavior
BaseUri
should be set to correctly constructed Uri
.
How to fix
Use the default ctor, it converts absolute paths correctly. This should work on Windows and Linux.
See https://dotnetfiddle.net/rHWSFJ and https://dotnetfiddle.net/M1ylXS.
Note: Keep in mind, that the usage differs a bit between Windows and Linux, absolute paths on Linux and Windows differ (Linux doesn't begin with a drive letter obviously ๐) so using Linux absolute path on Windows throws an exception, this is expected and correct behavior (I did test on .NET Framework and .NET Core 3.1, I did not test on Mono though).
Additional context
Introduced in version1.4.0
.
Describe the bug
"[]".AsJsonElement() will not return as array. It will return as a string;
To Reproduce
"[]".AsJsonElement() != JsonDocument.Parse("[]").RootElement
Expected behavior
A clear and concise description of what you expected to happen.
It should be a json array
Desktop (please complete the following information):
I've added a test (through much debate) to the test suite.
JSON Patch (RFC) is a format for describing changes to JSON documents.
Getting this from Nuget on publishing:
The symbol package JsonPath.Net 0.1.1 failed validation because of the following reason(s):
- The uploaded symbols package contains pdb(s) for a corresponding dll(s) not found in the nuget package.
Your symbol package was not published on NuGet Gallery and is not available for consumption.
You can reupload your symbol package once you've fixed the issue with it.
Doesn't occur with all packages. For example, the schema package seems to be fine.
Environment
Describe the bug
I met a Stack overflow
exception when I using Json.Schema.Generation
to generate schema from dotnet types.
I'm not sure whether it is suitable to describe my schema in dotnet types.
To Reproduce
create a class as below:
public class TestMenu
{
public string Name { get; set; }
public List<TestMenu> Children{ get; set; }
}
and call JsonSchema actual = new JsonSchemaBuilder().FromType<TestMenu>();
Expected behavior
output schema success
Additional context
none.
I'd expect the Detailed/Basic formatted results to not include validation errors if those errors wouldn't cause the entire document to be invalid (e.g. inside an AnyOf or an If/Then), as functions in Manatee.JsonSchema
Environment
How can I help you today?
I see in your documentation for JsonLogic that custom operators are coming. I was hoping to add one to help with case-insensitive comparisons. I was curious how close your library is to support adding a custom operator like this to handle some custom case-insensitive operations?
Thanks for all you've done!
.net core 3.1
I am trying to replicate the scenario specified in this official draft. Here is my code:
using Json.Pointer;
using Json.Schema;
using System;
using System.Text.Json;
namespace ConsoleApp1
{
class Program
{
static void GetErrorString(
ValidationResults results,
ref string errorString)
{
if (results.Message != null)
{
errorString += results.InstanceLocation + ": ";
errorString += results.Message + "\n";
}
foreach (var result in results.NestedResults)
GetErrorString(result, ref errorString);
}
static void Main(string[] args)
{
var schema = JsonSchema.FromFile("./point.json");
var jsnStr = @"[
{""x"": 2.5, ""y"":1.3},
{""x"": 1, ""z"":6.7}
]";
var jsnObj = JsonDocument.Parse(jsnStr).RootElement;
ValidationOptions options = new ValidationOptions();
options.OutputFormat = OutputFormat.Detailed;
options.ValidateAs = Draft.Draft201909;
var result = schema.Validate(jsnObj, options);
var errorString = "";
if(!result.IsValid)
GetErrorString(result, ref errorString);
Console.WriteLine(errorString);
}
}
}
This is my output:
#: Value has less than 3 items
#/1: Required properties [y] were not present
#/1/z: All values fail against the false schema
I noticed the error for pointer "#/1/z" is different to the one specified in the draft here which says: "Additional property 'z' found but was invalid".
This becomes especially problematic when I have the following schema:
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$id": "/CheckRequest",
"type": "object",
"properties": {
"code": {
"type": "string",
"minLength": 4,
"maxLength": 10
},
"phone": {
"type": "string",
"pattern": "^\\+[1-9]\\d{1,14}$"
}
},
"required": [ "code", "phone"],
"additionalProperties": false
}
with the following json instance:
var jsnStr = @"{
""code"": ""12555"",
""phone"":""357998765436"",
""extra"":""extra""
}";
Note: the phone input is invalid since it doesn not match the regex ( does not begin with a +) and my output becomes:
#/phone: The string value was not a match for the indicated regular expression
#/code: All values fail against the false schema
#/phone: All values fail against the false schema
#/extra: All values fail against the false schema
Why does this message (All values fail against the false schema) print for all my properties instead of just the "extra" property?
Thanks in advance
Describe the bug
I'm replacing ManateeJson with Json-everything and the unit test fails on this case
Expected behavior
To Reproduce
using Manatee.Json;
using Manatee.Json.Schema;
using System;
using System.Text.Json;
using JsonEverythingSchema = Json.Schema.JsonSchema;
using ManateeJsonSchema = Manatee.Json.Schema.JsonSchema;
using ManateeJsonSerializer = Manatee.Json.Serialization.JsonSerializer;
namespace jsonschema
{
class Program
{
private static readonly ManateeJsonSerializer _serializer = new ManateeJsonSerializer();
static void Main(string[] args)
{
Console.WriteLine($"Validate {MyJson} against {MySchema}");
ManateeValidation(MySchema, MyJson); // Expected Validation true
JsonEverythingValidation(MySchema, MyJson); // Expected Validation true
}
private static void JsonEverythingValidation(string schema, string json)
{
var jsSchema = JsonDocument.Parse(schema).RootElement;
var schemaValidationResult = Json.Schema.MetaSchemas.Draft7.Validate(jsSchema);
if (!schemaValidationResult.IsValid)
{
Console.Error.WriteLine($"JsonEverything: Schema is invalid - reason {schemaValidationResult.Message}");
return;
}
var jsonSchema = JsonEverythingSchema.FromText(schema);
var validationResult = jsonSchema.Validate(JsonDocument.Parse(json).RootElement);
Console.WriteLine($"JsonEverything: Valid {validationResult.IsValid} - {validationResult.Message}");
}
private static void ManateeValidation(string schema, string json)
{
var jsonSchema = _serializer.Deserialize<ManateeJsonSchema>(JsonValue.Parse(schema));
var schemaResult = jsonSchema.ValidateSchema();
if (!schemaResult.IsValid)
{
Console.Error.WriteLine("Manatee: Schema is invalid");
return;
}
if ((schemaResult.SupportedVersions & JsonSchemaVersion.Draft07) == 0)
{
Console.Error.WriteLine("Manatee: Schema is invalid expected draft 07");
return;
}
var validationResult = jsonSchema.Validate(JsonValue.Parse(json));
Console.WriteLine($"Manatee: Valid {validationResult.IsValid} - {validationResult.AdditionalInfo.ToString()}");
}
private static readonly string MyJson = @"
{
""prop1"": {
""name"": ""a"",
""version"": 1
},
""prop2"": {},
""prop4"": ""a"",
""prop5"": {},
""prop6"": {
""firstId"": ""428de96d-d5b2-4d12-8e88-37827099dd02"",
""secondId"": ""428de96d-d5b2-4d12-8e88-37827099dd02"",
""version"": ""test-version"",
""thirdId"": ""428de96d-d5b2-4d12-8e88-37827099dd02"",
""type"": ""test"",
""name"": ""testApp"",
""receiptTimestamp"": ""2019-02-05T12:36:31.2812022Z"",
""timestamp"": ""2012-04-21T12:36:31.2812022Z"",
""extra_key"": ""extra_val""
},
""prop3"": {
""prop5"": {},
""metadata"": {},
""deleteAfter"": 3,
""allowExport"": true
}
}
";
private static readonly string MySchema = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""type"": ""object"",
""required"": [""prop1"", ""prop2"", ""prop3"", ""prop4"", ""prop5"", ""prop6""],
""properties"": {
""prop1"": {
""type"": ""object"",
""required"": [""name"", ""version""],
""additionalProperties"": false,
""properties"": {
""name"": {
""type"": ""string"",
""pattern"": ""^[-_]?([a-zA-Z][-_]?)+$""
},
""version"": {
""type"": ""integer"",
""minimum"": 1
}
}
},
""prop2"": {
""$ref"": ""http://json-schema.org/draft-07/schema#""
},
""prop3"": {
""type"": ""object"",
""required"": [
""prop5"",
""metadata""
],
""additionalProperties"": false,
""properties"": {
""prop5"": {
""type"": ""object""
},
""metadata"": {
""type"": ""object""
},
""deleteAfter"": {
""type"": ""integer""
},
""allowExport"": {
""type"": ""boolean""
}
}
},
""prop4"": {
""type"": ""string"",
""pattern"": ""^[-_]?([a-zA-Z][-_]?)+$""
},
""prop5"": {
""type"": ""object""
},
""prop6"": {
""type"": ""object"",
""required"": [
""firstId"",
""secondId"",
""version"",
""thirdId"",
""type"",
""name"",
""receiptTimestamp"",
""timestamp""
],
""properties"": {
""firstId"": {
""type"": ""string"",
""pattern"": ""[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}""
},
""secondId"": {
""type"": ""string"",
""pattern"": ""[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}""
},
""type"": {
""type"": ""string"",
""enum"": [""test"", ""lab"", ""stage"", ""prod""]
},
""thirdId"": {
""type"": ""string"",
""pattern"": ""[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}""
},
""version"": {
""type"": ""string"",
""minLength"": 1
},
""name"": {
""type"": ""string"",
""minLength"": 1
},
""receiptTimestamp"": {
""type"": ""string"",
""format"": ""date-time""
},
""timestamp"": {
""type"": ""string"",
""format"": ""date-time""
}
},
""additionalProperties"": {
""type"": ""string""
}
}
},
""additionalProperties"": false
}
";
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JsonSchema.Net" Version="1.1.0" />
<PackageReference Include="Manatee.Json" Version="13.0.3" />
</ItemGroup>
</Project>
Describe the functionality that isn't covered by this suite
Hyperschema should be implemented.
Currently seems not possible, from a JsonSchema instance, to compare a JsonSchema with an other one. Are you going to support this?
Environment
How do validate a scalar value using a schema ? I want to achieve what is displayed in the screenshot below.
I see that Validate method only takes a JsonElement
and I am not sure how we can convert a scalar value to a JsonElement using the Parse APIs available. Any guidance would be appreciated.
Currently the badges point to Appveyor, which is old.
Environment
Describe the bug
I am creating a schema using JsonSchemaBuilder with a string type that i want to have an enum property. I have added it as such:
{
"type",
new JsonSchemaBuilder()
.Type(SchemaValueType.String)
.Enum("green".AsJsonElement(), "red".AsJsonElement())
}
I am expecting this output:
"type": {
"type": "string",
"enum": [
"green",
"red"
]
}
However i get this output:
"type": {
"type": "string",
"examples": [
"green",
"red"
]
}
JSONata ("j-sonata") is a query language for JSON data.
Describe the bug
If the value of $id
is not an absolute URL, resolving $ref
-s fails. This seems to have worked with ManateeJson; if removing this feature is intentional, we should probably still fail on de-serialization (i.e. validation) of the schema, instead of getting an exception when attempting to resolve the $ref
when using the schema to validate another json.
To Reproduce
using System;
using System.Text.Json;
using Json.Schema;
using Manatee.Json;
using ManateeJsonSerialiazer = Manatee.Json.Serialization.JsonSerializer;
using ManateeJsonSchema = Manatee.Json.Schema.JsonSchema;
namespace test
{
class Program
{
static void Main(string[] args)
{
var schemaStr = @"
{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""$id"": ""mySchema.json"",
""properties"": {
""abc"": { ""$ref"": ""mySchema.json"" }
},
""additionalProperties"": false
}";
var jsonStr = @"
{
""abc"": {
""abc"": {
""abc"": ""abc""
}
}
}";
var serializer = new ManateeJsonSerialiazer();
var manateeSchema = serializer.Deserialize<ManateeJsonSchema>(JsonValue.Parse(schemaStr));
var manateeJson = JsonValue.Parse(jsonStr);
var manateeValidation = manateeSchema.Validate(manateeJson);
Console.WriteLine("Manatee: {0}", serializer.Serialize(manateeValidation));
var schema = JsonSerializer.Deserialize<JsonSchema>(schemaStr);
var json = JsonDocument.Parse(jsonStr).RootElement;
var validation = schema.Validate(json);
validation.ToDetailed();
Console.WriteLine("JsonSchema.NET: {0}", JsonSerializer.Serialize(validation));
}
}
}
This throws an exception on the Validate
line - instead of throwing it at the Deserialize
one, or accepting this.
Expected behavior
I would expect partial URIs to be valid in $id
position, valid for use within the same document, and ideally also resolving to the base URI where the schema was obtained (allowing support across documents which share a base URI, even if it isn't specified inside the schema).
-OR-
If using partial URIs is strictly forbidden, I would expect this to be validated on schema de-serialization.
Also, as a side issue - I think it would also be better for $ref
-s to be resolved on de-serialization whenever possible. I'm not sure if this is possible for $recursiveRef
from draft2019-09, as the base URI can change there; but for $ref
it is fixed to the definition site, so this should be possible.
yeah, that...
Describe the bug
Unable to use decimal with all number based validators, like ExclusiveMaximumAttribute
.
To Reproduce
public class SomeEntity
{
[ExclusiveMaximum(75.00m)]
public decimal Percentage { get; set; }
}
Expected behavior
I believe the specification in draft-8/2019โ09 says any number
Describe the bug
The additionalProperties
keyword is being treated as a property.
To Reproduce
using System;
using System.Text.Json;
using Json.Schema;
var schema = @"{
""$schema"": ""http://json-schema.org/draft-07/schema#"",
""additionalProperties"": false
}";
var data = @"{
""prop1"":""val""
}";
var jsonSchema = JsonSchema.FromText(schema);
var validationResult = jsonSchema.Validate(JsonDocument.Parse(data).RootElement, new ValidationOptions { OutputFormat = OutputFormat.Basic });
Console.WriteLine(JsonSerializer.Serialize(validationResult));
//outputs
{
"valid": false,
"keywordLocation": "#/additionalProperties/$false",
"instanceLocation": "#/prop1",
"error": "All values fail against the false schema"
}
Expected behaviour
The error should indicate that additional properties is present.
Desktop (please complete the following information):
Can this library make doing something simpler?
I would like to be able to extract the schema from an object example or from a json example. You have this possibilities in other language like js with to-json-schema (https://www.npmjs.com/package/to-json-schema) or in NJsonSchema (https://github.com/RicoSuter/NJsonSchema/blob/master/src/NJsonSchema/Generation/SampleJsonSchemaGenerator.cs)
Describe alternatives you've considered
It could be an extension of JsonSchema class like that
// From text.
var schema = JsonSchema.FromSample("json text");
// From a JsonDocument
var schema = JsonSchema.FromSample(jsonDocumentInstance);
// Directly from an object instance
var schema = JsonSchema.FromSample<Sample>(sampleInstance);
I've an object with this schema.
public class Person
{
[JsonPropertyName("_id")]
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
Schema generation extension generate a schema with a id property and not an _id property.
Can this library make doing something simpler?
I'd like to be able to use typed objects to parse JSonPointer
Additional context
The JSonPatch lib i'm currently using is having typed object and that makes it a lot more easier to maintain than hardcoded string.
var patch = new JsonPatchDocument<Item>();
patch.Replace(link => link.Price, newPrice);
I'd like to be able to load references ($ref
keyword) from local file system using relative paths.
I tried this as well with Manatee.Json
. I figured out I have to set DocumentPath
which concatenated the relative path with the absolute path I set to DocumentPath
and then failed when separating the URI from the JSON Pointer to the schema within the file.
With Newtonsoft.Json.Schema
this works by passing the following settings:
var schemaFullPath = Path.GetFullPath(schemaFile);
var settings = new JSchemaReaderSettings
{
BaseUri = new Uri(schemaFullPath),
Resolver = new JSchemaUrlResolver(),
};
To make this work each JsonSchema
needs to have a CurrentUri
(since the file locations on the file system may change, using $id
isn't really an option) so that it can be set to context.CurrentUri
. This way RefKeyword.Validate
will create a proper Uri
pointing to the file to load. Dynamic loading of files that Manatee
supports would be nice. Maybe a simple delegate that the user can set would do the job.
$id
at runtime by mutating the JSON (parsing it, modifying and serializing) then passing it to FromText
(which deserializes it again).SchemaRegistry
.This have the benefit of loading all schemas prior any validation.
However this isn't really a straight forward solution (as it requires about 200 LOC).
Environment
Describe the bug
Generating the same scheme FromType multimpe times and then veryfying some JsonElement with it causes StackOverflow. The place of schema definition doesn't matter: two times in main, one time in main and one time in the callable function, etc.
To Reproduce
using Json.Schema;
using Json.Schema.Generation;
using System.Text.Json;
public class SimpleValueWidgetSettings
{
[Required]
public string name { get; set; }
[Required]
public string valueLink { get; set; }
[Required]
public string qualityValueLink { get; set; }
[Required]
public string unitLink { get; set; }
[Required]
public string displayMultiplier { get; set; }
[Required]
public string displayUnits { get; set; }
[Required]
public string fontColor { get; set; }
[Required]
public string stringFormat { get; set; }
static void Main(string[] args)
{
var simpleValueJson = "{\"name\":\"LD2/ATCC1.CtlV.db\"}";
var simpleValueParsed = JsonDocument.Parse(simpleValueJson).RootElement;
var simpleValueParsed2 = JsonDocument.Parse(simpleValueJson).RootElement;
var simpleValueSettingsSchema2 = new JsonSchemaBuilder().FromType<SimpleValueWidgetSettings>().AdditionalProperties(false).Build();
var simpleValueSettingsSchema = new JsonSchemaBuilder().FromType<SimpleValueWidgetSettings>().AdditionalProperties(false).Build();
simpleValueSettingsSchema.Validate(simpleValueParsed);
simpleValueSettingsSchema.Validate(simpleValueParsed2);
}
}
Expected behavior
Validating without causing StackOverflow. Multiple definition of the same schema shouldn't cause StackOverflow when trying to validate some JsonElement with the last one.
Feature Request
Add strong-name signing to the JsonSchema.Net project so that strong-name signed projects can also use JsonSchema.Net.
We're keen to use this in an enterprise setting which requires strong-name signing from dependent nuget packages.
Issue faced when strong-name is not present
Message:
System.IO.FileLoadException : Could not load file or assembly 'JsonSchema.Net, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
Describe alternatives you've considered
Other open source libraries have similar issue on strong-names:
e.g. auth0/auth0.net#207
I've tried the suggested strong namer nuget packages:
However, the above strong namers were not able to resolve the dependent Json.More package.
auth0 open source library ended up adding strong name to resolve the issue also.
Reference Demo
I've created the following VS solution to replicate the issue:
https://github.com/whatevergeek/JsonSchemaDemo
Currently, it fails when running the tests in JsonSchemaDemoTest because of the mentioned strong name issue.
OAS 3.1 will be using 2020-12. This means we can create a lib to encapsulate the vocab and metaschema.
It doesn't look like there's a metaschema yet. Will need to wait on that before publishing, but I can start defining keywords, maybe.
Static analysis for JSON Schema. Could include rules for things like
$schema
$defs
oneOf
instead of multiple levels of nested if
/then
/else
true
schema instead of {}
Environment
Describe the bug
I am trying to write an IAttributeHandler
that will use the System.ComponentModel.DataAnnotations.DisplayAttribute to set a title and description for a schema, but the handler's AddConstraints
method never seems to get called, despite the handler being registered via the AttributeHandler.AddHandler<T>
method.
Based on the instructions here for writing a handler for an attribute in an external assembly, I can't tell if there is something else that I am supposed to do.
To Reproduce
void Main() {
AttributeHandler.AddHandler<DisplayAttributeHandler>();
var schema = new JsonSchemaBuilder().FromType<MyType>().Build();
Console.WriteLine(JsonSerializer.Serialize(schema, new JsonSerializerOptions {
WriteIndented = true
}));
}
public class DisplayAttributeHandler : IAttributeHandler {
public DisplayAttributeHandler() {
Console.WriteLine("Constructor called");
}
public void AddConstraints(SchemaGeneratorContext context) {
Console.WriteLine("AddConstraints called");
// TODO: update the context
}
}
public class MyType {
[System.ComponentModel.DataAnnotations.Display(Name = "Test Name", Description = "Test description")]
public string SomeProperty { get; set; }
}
When I run the above program, I get the following output (note that the Console.WriteLine
statements in my handler are never called):
{
"type": "object",
"properties": {
"SomeProperty": {
"type": "string"
}
}
}
Expected behavior
Handlers registered via AttributeHandler.AddHandler<T>
should be invoked when a schema is being built.
Additional context
When I added a Console.WriteLine
statement to my handler's constructor, I could see that the handler is never even instantiated.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.