Comments (16)
I think i found the problem. It's the JsonNodeExtensions.GetInteger
method in Json.More. Note that it misses a TryGetValue for uint
values (it has ushort
mistakenly twice):
json-everything/Json.More/JsonNodeExtensions.cs
Lines 183 to 203 in 02c06ae
from json-everything.
I have updated Json.More.Net to 2.0.1. Issue is fixed. Thank you very much.
from json-everything.
Can you please provide both the code that produces the JsonSchema object as well as as the json document that exhibits this issue? I did a quick test (obviously i had to make my own schema and json document), and i cannot reproduce the issue you describe with 6.0.3...
from json-everything.
Hi I can provide only snippets of code(general pattern):
public static readonly JsonSchema GenericSchema = new JsonSchemaBuilder()
.Type(SchemaValueType.Object)
.Schema(MetaSchemas.Draft7Id)
.Description(
"Configuration file.")
.Properties(new Dictionary<string, JsonSchema>
{
{
"genericId", new JsonSchemaBuilder()
.Type(SchemaValueType.String)
.MinLength(11)
.MaxLength(11)
.Description("A unique identifier for the device and connected infrastructure.")
.Build()
},
{
"heartbeatId", new JsonSchemaBuilder()
.Type(SchemaValueType.String)
.MinLength(11)
.MaxLength(11)
.Description("Heartbeat ID of the device.")
.Build()
},
{
"components", new JsonSchemaBuilder()
.Type(SchemaValueType.Array)
.MinItems(1)
.Items(new JsonSchemaBuilder().OneOf(
new JsonSchemaBuilder().Ref(new Uri("sunComponent",
UriKind.RelativeOrAbsolute))))
}
})
.Defs(new Dictionary<string, JsonSchema>
{
{ "sunComponent", ComponentSchemas..SunComponent},
{ "componentSchema", ComponentSchemas.GenericComponentSchema },
{ "specificComponentSchema", SpecificComponentSchemas.SpecificComponentSchema },
{ "componentTypeSchema", ComponentSchemas.ComponentTypeSchema() },
})
.Required("genericId",
"heartbeatId", "components")
.AdditionalProperties(false);
Json document is created as described JsonSerializer.Serialize(MySchemaObject.Schema) and saved to file.
In 5.5.1 I to evaluate json I used only MySchemaObject.Schema.Evaluate(jsonDocumentInstance). After upgrade to 6.0.x it only works if if serialize schema object and then evaluate json.
from json-everything.
Still not reproducible, unfortunately.
Your code example is still not complete (it lacks the definition of the SunComponent schema refered to by the "components"
property. And the Uri used for the $ref is incorrect, considering that the SunComponent schema is in a $defs
block. Both 5.5.1 and 6.0.3 do not accept this Uri with respect to the schema code you provided.
Fixing the sunComponent $ref Uri (from new Uri("sunComponent", UriKind.RelativeOrAbsolute)
to new Uri("#/$defs/sunComponent", UriKind.RelativeOrAbsolute)
) as well as inventing my own SunComponent schema, i observe 6.0.3 behaves the same as 5.5.1 with both evaluationResultFromSchema
and directEvaluationResult
results being valid.
I'd like to provide a dotnetfiddle that proves (or disproves, if i am unlucky) that 6.0.3 behaves like 5.5.1 with the code given, but dotnetfiddle currently times out when trying to fetch the JsonSchema.Net 6.0.3 package. Hrmpf...
Therefore, i'd suggest you inspect the (hierarchical) Details
collection of the invalid evaluation result to see (A) which part of the schema and (B) which part of the validated json data is contributing to the invalid result. That should help you hone in on which parts of the schema and the validated json data are likely relevant to the issue you observe, which might be helpful to either identify the issue or provide guidance for you to produce a complete reproduction code and json data exhibiting the issue.
from json-everything.
Unfortunately I can't provide my real json definitions and json schema.
In the case when I evaluate schema directly:
var directEvaluationResult = MySchemaObject.Schema.Evaluate(jsonDocumentInstance);
I get [oneOf, Expected 1 matching subschema but found 0]
but when I execute same code using:
var schemaFromString = JsonSchema.FromText(JsonSerializer.Serialize(MySchemaObject.Schema));
var evaluationResultFromSchema = schemaFromString.Evaluate(jsonDocumentInstance);
evaluationResultFromSchema.IsValid is valid.
from json-everything.
Unfortunately I can't provide my real json definitions and json schema.
Okay. Then try using the list output format, if you have not done so already, i.e.:
var evaluationResultFromSchema = schemaFromString.Evaluate(jsonDocumentInstance, new EvaluationOptions { OutputFormat = OutputFormat.List });
var directEvaluationResult = Schemas.GenericSchema.Evaluate(jsonDocumentInstance, new EvaluationOptions { OutputFormat = OutputFormat.List });
Crawl the Details
collection of the evaluation result for any item that has its HasErrors
property set to true. Of those items, take note of the InstanceLocation
(that points to the part in the validated json data that fails validation) and SchemaLocation
(pointing to the part of the (sub) schema that produces a failing validation). This should give you more context about which parts of your json data are failing to be validated by which parts of your schema(s). Hopefully this can help you honing in on the issue.
from json-everything.
Just as an FYI:
This is the dotnetfiddle i was trying to provide: https://dotnetfiddle.net/1hQdMT (Update: dotnetfiddle is working again. Updated my dotnetfiddle link with the working fiddle...)
By the way, i did my tests with both the .net8 flavor (for 6.0.3) as well as the .netstandard20 flavor (for both 6.0.3 and 5.5.1) of JsonSchema.Net and the respective dependencies JsonSchema.Net relies on in a console application with .net8 as target framework. As said, i did not observe any difference between 5.5.1 and 6.0.3.
from json-everything.
Unfortunately I can't provide my real json definitions and json schema. - @ZarkoRunjevac
If you'd like to DM me in Slack, I may be able to help further. I keep everything confidential, and because it's a free workspace, it'll eventually be lost to the void.
from json-everything.
Hi, I managed to narrow down issue:
My test code is:
Schema and model definition:
public static class Schemas
{
private static JsonSchema BuildingTypeIdSchema()
{
var enumValues = Enum.GetValues(typeof(BuildingTypeId))
.Cast<BuildingTypeId>();
var oneOfList = enumValues.Select(value => new JsonSchemaBuilder().Const((uint)value)
.Title(value.ToString())
.Build())
.ToList();
return new JsonSchemaBuilder()
.OneOf(oneOfList)
.AdditionalProperties(false)
.Build();
}
private static JsonSchema BuildingTypeSchema()
{
var enumValues = Enum.GetValues(typeof(BuildingType))
.Cast<BuildingType>();
var oneOfList = enumValues.Select(value => new JsonSchemaBuilder().Const((uint)value)
.Title(value.ToString())
.Build())
.ToList();
return new JsonSchemaBuilder()
.OneOf(oneOfList)
.AdditionalProperties(false)
.Build();
}
public static readonly JsonSchema BuildingSchema = new JsonSchemaBuilder()
.Properties(new Dictionary<string, JsonSchema>
{
{
"id", new JsonSchemaBuilder()
.Type(SchemaValueType.Integer)
.Build()
},
{
"buildingType", new JsonSchemaBuilder()
.Type(SchemaValueType.Integer)
.Ref(new Uri("#/$defs/buildingType", UriKind.RelativeOrAbsolute))
},
{
"buildingTypeId", new JsonSchemaBuilder()
.Type(SchemaValueType.Integer)
.Ref(new Uri("#/$defs/buildingTypeId", UriKind.RelativeOrAbsolute))
}
})
.Defs(new Dictionary<string, JsonSchema>
{
{ "buildingType", BuildingTypeSchema() },
{ "buildingTypeId", BuildingTypeIdSchema() },
})
.Required("id",
"buildingType",
"buildingTypeId")
.AdditionalProperties(false)
.Build();
}
public class Building
{
[JsonPropertyName("id")] public uint Id { get; set; }
[JsonPropertyName("buildingType")] public BuildingType BuildingType { get; set; }
[JsonPropertyName("buildingTypeId")] public BuildingTypeId BuildingTypeId { get; set; }
}
public enum BuildingType : uint
{
Type0 = 0,
Type1 = 1,
Type2 = 2,
Type5 = 5,
Type8 = 8,
Type13 = 13,
Type19 = 19,
Type40 = 40,
Type48 = 48
}
public enum BuildingTypeId : uint
{
Current = 85,
System = 112
}
Program.cs:
using System.Text.Json;
using Json.Schema;
using Schema;
var json = @"{
""id"": 23,
""buildingType"": 19,
""buildingTypeId"": 85
}";
var jsonDocumentInstance = JsonDocument.Parse(json);
var schemaText = JsonSerializer.Serialize(Schemas.BuildingSchema);
var schemaFromString = JsonSchema.FromText(schemaText);
var directEvaluationResult = Schemas.BuildingSchema.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
var evaluationResultFromSchema = schemaFromString.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
Console.WriteLine(directEvaluationResult.IsValid);
Console.WriteLine(evaluationResultFromSchema.IsValid);
When version 5.5.1 version is used directEvaluationResult and evaluationResultFromSchema are valid, but on 6.0.3
evaluationResultFromSchema is only valid.
from json-everything.
Alright, i can reproduce. And i can dramatically simplify the repro code and narrow down to what triggers the bug. It appears the issue is caused by using uint
values for building the const schemas in new JsonSchemaBuilder().Const((uint)value)
.
Simplified reproduction code that demonstrates the issue occurring with uint
const values but not with int
const values:
using System.Text.Json;
using System.Text.Json.Serialization;
using Json.Schema;
var schemaWithInt = new JsonSchemaBuilder()
.Title("Schema with const Int")
.Properties(("prop", new JsonSchemaBuilder().Const((int)1)))
.AdditionalProperties(false)
.Build();
var schemaWithUInt = new JsonSchemaBuilder()
.Title("Schema with const UInt")
.Properties(("prop", new JsonSchemaBuilder().Const((uint)1)))
.AdditionalProperties(false)
.Build();
TestSchema(schemaWithInt);
Console.WriteLine();
TestSchema(schemaWithUInt);
static void TestSchema(JsonSchema schema)
{
var json = """{"prop":1}""";
var jsonDocumentInstance = JsonDocument.Parse(json);
var schemaText = JsonSerializer.Serialize(schema);
var schemaFromString = JsonSchema.FromText(schemaText);
var directEvaluationResult = schema.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
var evaluationResultFromSchema = schemaFromString.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
Console.WriteLine(schema.GetTitle());
Console.WriteLine(directEvaluationResult.IsValid);
Console.WriteLine(evaluationResultFromSchema.IsValid);
}
dotnetfiddle: https://dotnetfiddle.net/Gk2Ghy
from json-everything.
Thanks @elgonzo. One more thing to check is the JsonNode.IsEquivalentTo()
extension method for int
s and uint
s.
That's in Json.More.Net, so it may not be a schema issue.
from json-everything.
Also in the GetInteger
method, the ulong
handling is definitely incorrect too (as the code comment already implies):
json-everything/Json.More/JsonNodeExtensions.cs
Lines 199 to 200 in 02c06ae
This will for example make schema validation fail exactly in the same manner as described by OP when building const schema instances using ulong
values that exceed the value range of the long
type. Repo code:
var schemaWithLargeULong = new JsonSchemaBuilder()
.Title("Schema with large const ULong")
.Properties(("prop", new JsonSchemaBuilder().Const(10_000_000_000_000_000_000)))
.AdditionalProperties(false)
.Build();
var json = """{"prop":10000000000000000000}""";
var jsonDocumentInstance = JsonDocument.Parse(json);
var schemaText = JsonSerializer.Serialize(schema);
var schemaFromString = JsonSchema.FromText(schemaText);
var directEvaluationResult = schema.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
var evaluationResultFromSchema = schemaFromString.Evaluate(jsonDocumentInstance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
ValidateAgainstMetaSchema = true,
RequireFormatValidation = true
});
Console.WriteLine(schema.GetTitle());
Console.WriteLine(directEvaluationResult.IsValid);
Console.WriteLine(evaluationResultFromSchema.IsValid);
dotnetfiddle: https://dotnetfiddle.net/HxwJgb
Not sure what the best approach would be to address this ulong issue, though, since GetInteger
is a public API. Perhaps adjusting the GetNumber
method would be sufficient, placing a value.TryGetValue(out ulong)
check before the call of GetInteger? Something like this:
public static decimal? GetNumber(this JsonValue value)
{
if (value.TryGetValue(out JsonElement e))
{
if (e.ValueKind != JsonValueKind.Number) return null;
return e.GetDecimal();
}
if (value.TryGetValue(out ulong ul)) return ul;
var number = GetInteger(value);
if (number != null) return number;
...
from json-everything.
Yeah, I didn't know what to do with ulong
. I realize that my approach wasn't... great. I like the approach of checking first in .GetNumber()
. For external callers, I expect a note in the XML comments and in the docs will have to do.
from json-everything.
I've added a test in the JsonSchema suite that replicates @elgonzo's example.
PR is ☝️
from json-everything.
@ZarkoRunjevac Json.More.Net 2.0.1 will be pushed out soon. Please update to that in your project to confirm the fix.
from json-everything.
Related Issues (20)
- How to get list of JSON Pointers that have the format keyword of date-time value from a JSON Schema HOT 4
- Support xml comments on generated schema HOT 13
- Deconstruct JsonLogic for conversion into another format HOT 8
- Support Case Insensitive Match on Property Names HOT 2
- Support custom keywords in schema generation HOT 6
- Evaluate JsonRequired Attribute HOT 5
- Model with Nullable value type is invalid HOT 1
- Model is not valid when has integer value as string HOT 1
- that the custom metastructure could not be parsed HOT 4
- How to extend SchemaGenerator for DateTime HOT 7
- JsonSchema.NET DataValidation HOT 10
- Custom `IAttributeHandler` never called HOT 5
- Anchors naming of 2020 still following 2019 rules HOT 5
- Generating a Custom JSON Schema HOT 1
- ArgumentOutOfRangeException thrown when calling JsonSchema's Evaluate methods from multiple threads. HOT 3
- 2020-12 output incorrectly places annotations
- Nullable decimal type removes multipleOf HOT 1
- Boolean applicator keywords must be non-empty HOT 1
- Issues with rendering on docs site HOT 1
- Verified error reporting type HOT 18
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from json-everything.