From 5548a73c16839365c94259110f6eeaecc9dea7d9 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:33:46 +0600 Subject: [PATCH 1/4] Update data type validation process --- JsonSchema/JsonSchema.csproj | 6 +- .../JsonSchema/Tree/RuntimeContext.cs | 18 ++++- .../RelogicLabs/JsonSchema/Types/JDataType.cs | 68 +++++++++++-------- .../JsonSchema/Types/JValidator.cs | 13 +++- README.md | 21 +++--- 5 files changed, 78 insertions(+), 48 deletions(-) diff --git a/JsonSchema/JsonSchema.csproj b/JsonSchema/JsonSchema.csproj index 1c9dcdd..bd0024a 100644 --- a/JsonSchema/JsonSchema.csproj +++ b/JsonSchema/JsonSchema.csproj @@ -5,9 +5,9 @@ A simplified, concise, intuitive, and extensible JSON Schema Relogic Labs Relogic Labs - 1.4.0 - 1.4.0 - 1.4.0 + 1.5.0 + 1.5.0 + 1.5.0 JsonSchema;Schema;Json;Validation;Assert;Test Copyright © Relogic Labs. All rights reserved. en diff --git a/JsonSchema/RelogicLabs/JsonSchema/Tree/RuntimeContext.cs b/JsonSchema/RelogicLabs/JsonSchema/Tree/RuntimeContext.cs index fbe40e6..7b1ebe1 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Tree/RuntimeContext.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Tree/RuntimeContext.cs @@ -9,6 +9,7 @@ public class RuntimeContext { private readonly FunctionManager _functionManager; private readonly PragmaManager _pragmaManager; + private int _disableCount; internal MessageFormatter MessageFormatter { get; set; } public bool ThrowException { get; set; } @@ -59,10 +60,23 @@ public JDefinition AddDefinition(JDefinition definition) internal bool AreEqual(double value1, double value2) => Math.Abs(value1 - value2) < FloatingPointTolerance; + internal T TryMatch(Func function) + { + try + { + _disableCount += 1; + return function(); + } + finally + { + _disableCount -= 1; + } + } + internal bool FailWith(Exception exception) { - if(ThrowException) throw exception; - Exceptions.Enqueue(exception); + if(ThrowException && _disableCount == 0) throw exception; + if(_disableCount == 0) Exceptions.Enqueue(exception); return false; } } \ No newline at end of file diff --git a/JsonSchema/RelogicLabs/JsonSchema/Types/JDataType.cs b/JsonSchema/RelogicLabs/JsonSchema/Types/JDataType.cs index 85e53f3..097e806 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Types/JDataType.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Types/JDataType.cs @@ -4,6 +4,7 @@ using RelogicLabs.JsonSchema.Utilities; using static RelogicLabs.JsonSchema.Message.ErrorCode; using static RelogicLabs.JsonSchema.Message.ErrorDetail; +using static RelogicLabs.JsonSchema.Message.MatchReport; namespace RelogicLabs.JsonSchema.Types; @@ -14,7 +15,7 @@ public class JDataType : JBranch, INestedMode public required JAlias? Alias { get; init; } public required bool Nested { get; init; } public override IEnumerable Children => _children; - + internal JDataType(IDictionary relations) : base(relations) { } internal override JNode Initialize() @@ -27,51 +28,60 @@ internal override JNode Initialize() public override bool Match(JNode node) { - if(!Nested) return JsonType.Match(node); - if(node is not JComposite composite) return FailWith( - new JsonSchemaException( - new ErrorDetail(DTYP02, InvalidNestedDataType), - ExpectedDetail.AsInvalidDataType(this), - ActualDetail.AsInvalidDataType(node))); + if(!Nested) return _MatchCurrent(node); + if(node is not JComposite composite) return false; IList components = composite.GetComponents(); - return components.Select(MatchCurrent).AllTrue(); + return components.Select(_MatchCurrent).AllTrue(); } - private bool MatchCurrent(JNode node) + private bool _MatchCurrent(JNode node) + => MatchCurrent(node) == Success; + + private MatchReport MatchCurrent(JNode node) { - bool result = true; - result &= JsonType.Match(node); - if(Alias == null) return result; + var result = JsonType.Match(node) ? Success : TypeError; + if(Alias == null || result != Success) return result; Runtime.Definitions.TryGetValue(Alias, out var validator); - if(validator == null) return FailWith(new DefinitionNotFoundException( - MessageFormatter.FormatForSchema(DEFI03, Alias.Name, Context))); - result &= validator.Match(node); + if(validator == null) return AliasError; + result = validator.Match(node) ? Success : ArgumentError; return result; } internal bool MatchForReport(JNode node) { - if(!Nested && !JsonType.Match(node)) return FailWith( - new JsonSchemaException(new ErrorDetail(DTYP04, DataTypeMismatch), - ExpectedDetail.AsDataTypeMismatch(this), - ActualDetail.AsDataTypeMismatch(node))); + if(!Nested) return MatchForReport(node, false); if(node is not JComposite composite) return FailWith( new JsonSchemaException( - new ErrorDetail(DTYP05, InvalidNestedDataType), - ExpectedDetail.AsInvalidDataType(this), - ActualDetail.AsInvalidDataType(node))); + new ErrorDetail(DTYP03, InvalidNestedDataType), + ExpectedDetail.AsInvalidNestedDataType(this), + ActualDetail.AsInvalidNestedDataType(node))); IList components = composite.GetComponents(); bool result = true; - foreach(var c in components) - { - if(!MatchCurrent(c)) result &= FailWith(new JsonSchemaException( - new ErrorDetail(DTYP06, DataTypeMismatch), - ExpectedDetail.AsDataTypeMismatch(this), - ActualDetail.AsDataTypeMismatch(c))); - } + foreach(var c in components) result &= MatchForReport(c, true); return result; } + private bool MatchForReport(JNode node, bool nested) + { + var result = MatchCurrent(node); + if(ReferenceEquals(result, TypeError)) return FailWith( + new JsonSchemaException( + new ErrorDetail(TypeError.GetCode(nested), DataTypeMismatch), + ExpectedDetail.AsDataTypeMismatch(this), + ActualDetail.AsDataTypeMismatch(node))); + if(ReferenceEquals(result, AliasError)) return FailWith( + new DefinitionNotFoundException( + MessageFormatter.FormatForSchema(AliasError.GetCode(nested), + $"No definition found for {Alias!.Name}", Context))); + if(ReferenceEquals(result, ArgumentError)) return FailWith( + new JsonSchemaException( + new ErrorDetail(ArgumentError.GetCode(nested), + DataTypeArgumentFailed), + ExpectedDetail.AsDataTypeArgumentFailed(this), + ActualDetail.AsDataTypeArgumentFailed(node))); + return true; + } + public override bool Equals(object? obj) { if(ReferenceEquals(null, obj)) return false; diff --git a/JsonSchema/RelogicLabs/JsonSchema/Types/JValidator.cs b/JsonSchema/RelogicLabs/JsonSchema/Types/JValidator.cs index 6fa1a7d..c1bb2be 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Types/JValidator.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Types/JValidator.cs @@ -40,7 +40,6 @@ public override bool Match(JNode node) ExpectedDetail.AsValueMismatch(Value!), ActualDetail.AsValueMismatch(node))); var rDataType = MatchDataType(node); - if(!rDataType) DataTypes.ForEach(d => d.MatchForReport(node)); var fDataType = rDataType && DataTypes.Count != 0; bool rFunction = Functions.Where(f => f.IsApplicable(node) || !fDataType) .Select(f => f.Match(node)).ForEachTrue() || Functions.Count == 0; @@ -48,13 +47,21 @@ public override bool Match(JNode node) } private bool MatchDataType(JNode node) + { + if(Runtime.TryMatch(() => CheckDataType(node))) return true; + DataTypes.Where(d => !d.Nested).ForEach(d => d.MatchForReport(node)); + DataTypes.Where(d => d.Nested).ForEach(d => d.MatchForReport(node)); + return false; + } + + private bool CheckDataType(JNode node) { var list1 = DataTypes.Where(d => !d.Nested).Select(d => d.Match(node)).ToList(); - var result1 = list1.AnyTrue() || list1.Count == 0; + var result1 = list1.AnyTrue(); var list2 = DataTypes.Where(d => d.Nested && (d.IsApplicable(node) || !result1)) .Select(d => d.Match(node)).ToList(); var result2 = list2.AnyTrue() || list2.Count == 0; - return result1 && result2; + return (result1 || list1.Count == 0) && result2; } public override string ToString() => ( diff --git a/README.md b/README.md index 42c52ad..3dd46be 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ The next example represents an expanded version of the previous one, which bring %title: "Extended User Profile Dashboard API Response" %version: 2.0.0 %include: RelogicLabs.JsonSchema.Tests.Positive.ExternalFunctions, - RelogicLabs.JsonSchema.Tests + RelogicLabs.JsonSchema.Tests %pragma IgnoreUndefinedProperties: true @@ -92,7 +92,7 @@ The next example represents an expanded version of the previous one, which bring } #object #null } -%define $tags: @length(1, 10) #array($tag) +%define $tags: @length(1, 10) #string*($tag) #array %define $tag: @length(3, 20) @regex("[A-Za-z_]+") #string %schema: @@ -101,10 +101,9 @@ The next example represents an expanded version of the previous one, which bring "id": @range(1, 10000) #integer, /*username does not allow special characters*/ "username": @regex("[a-z_]{3,30}") #string, - /*currently only one role is allowed by system*/ - "role": "user" #string, + "role": @enum("user", "admin") #string, "isActive": #boolean, //user account current status - "registeredAt": #time, + "registeredAt": @time("DD-MM-YYYY hh:mm:ss") #string, "profile": { "firstName": @regex("[A-Za-z]{3,50}") #string, "lastName": @regex("[A-Za-z]{3,50}") #string, @@ -139,9 +138,9 @@ The subsequent JSON sample is an illustrative example that successfully validate "user": { "id": 1234, "username": "johndoe", - "role": "user", + "role": "admin", "isActive": true, - "registeredAt": "2023-09-06T15:10:30.639Z", + "registeredAt": "06-09-2023 15:10:30", "profile": { "firstName": "John", "lastName": "Doe", @@ -209,9 +208,9 @@ The subsequent JSON sample is an illustrative example that successfully validate "price": 1299.99, "inStock": false, "specs": { - "cpu": "Intel i7", - "ram": "16GB", - "storage": "512GB SSD" + "cpu": "Intel i11", + "ram": "11GB", + "storage": "11GB SSD" } } ], @@ -222,4 +221,4 @@ The subsequent JSON sample is an illustrative example that successfully validate } } ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](https://relogiclabs.github.io/JsonSchema-DotNet/api/index.html). +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](https://relogiclabs.github.io/JsonSchema-DotNet/api/index.html). \ No newline at end of file From a9dee02ba0abf2184d30c35a5b845e28f1506be8 Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:50:07 +0600 Subject: [PATCH 2/4] Update error codes and messages --- .../JsonSchema/Message/ActualDetail.cs | 35 ++++++++-------- .../JsonSchema/Message/ErrorCode.cs | 2 + .../JsonSchema/Message/ErrorDetail.cs | 11 ++--- .../JsonSchema/Message/ExpectedDetail.cs | 40 ++++++++++--------- .../JsonSchema/Message/MatchReport.cs | 25 ++++++++++++ .../RelogicLabs/JsonSchema/Types/JNode.cs | 2 +- .../JsonSchema/Utilities/DebugUtils.cs | 2 +- 7 files changed, 75 insertions(+), 42 deletions(-) create mode 100644 JsonSchema/RelogicLabs/JsonSchema/Message/MatchReport.cs diff --git a/JsonSchema/RelogicLabs/JsonSchema/Message/ActualDetail.cs b/JsonSchema/RelogicLabs/JsonSchema/Message/ActualDetail.cs index 8697470..2f133bf 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Message/ActualDetail.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Message/ActualDetail.cs @@ -8,36 +8,39 @@ namespace RelogicLabs.JsonSchema.Message; public class ActualDetail : ContextDetail { [SetsRequiredMembers] - public ActualDetail(Context context, string message) + public ActualDetail(Context context, string message) : base(context, message) { } - + [SetsRequiredMembers] - public ActualDetail(JNode node, string message) + public ActualDetail(JNode node, string message) : base(node, message) { } internal static ActualDetail AsValueMismatch(JNode node) => new(node, node.GetOutline().Affix("found ")); - - internal static ActualDetail AsPropertyNotFound(JNode node, JProperty property) - => new(node, $"not found property key \"{property.Key}\""); - + + internal static ActualDetail AsPropertyNotFound(JNode node, JProperty property) + => new(node, $"not found property key '{property.Key}'"); + internal static ActualDetail AsUndefinedProperty(JProperty property) => new(property, $"property found {{{property.GetOutline()}}}"); - - internal static ActualDetail AsDataTypeMismatch(JNode node) + + internal static ActualDetail AsDataTypeMismatch(JNode node) => new(node, $"found {GetTypeName(node)} inferred by {node.GetOutline()}"); internal static ActualDetail AsArrayElementNotFound(JArray array, int index) => new(array, "not found"); - - internal static ActualDetail AsInvalidFunction(JNode node) - => new(node, $"applied on non-composite type {GetTypeName(node)}"); - - internal static ActualDetail AsInvalidDataType(JNode node) + + internal static ActualDetail AsInvalidFunction(JNode node) => new(node, $"applied on non-composite type {GetTypeName(node)}"); + internal static ActualDetail AsInvalidNestedDataType(JNode node) + => new(node, $"found non-composite type {GetTypeName(node)}"); + + internal static ActualDetail AsDataTypeArgumentFailed(JNode node) + => new(node, $"found invalid value {node.GetOutline()}"); + internal static ActualDetail AsPropertyOrderMismatch(JNode node) => node is JProperty property - ? new(property, $"key \"{property.Key}\" is found at position") - : new(node, "key not found at position"); + ? new(property, $"key '{property.Key}' is found at current position") + : new(node, "key not found at current position"); } \ No newline at end of file diff --git a/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorCode.cs b/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorCode.cs index 68014b4..f94c66a 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorCode.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorCode.cs @@ -32,6 +32,7 @@ internal static class ErrorCode public const string DEFI01 = "DEFI01"; public const string DEFI02 = "DEFI02"; public const string DEFI03 = "DEFI03"; + public const string DEFI04 = "DEFI04"; public const string DERA01 = "DERA01"; public const string DERA02 = "DERA02"; public const string DFRC01 = "DFRC01"; @@ -71,6 +72,7 @@ internal static class ErrorCode public const string DTYP04 = "DTYP04"; public const string DTYP05 = "DTYP05"; public const string DTYP06 = "DTYP06"; + public const string DTYP07 = "DTYP07"; public const string DUBL01 = "DUBL01"; public const string DUTC01 = "DUTC01"; public const string DUTC02 = "DUTC02"; diff --git a/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorDetail.cs b/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorDetail.cs index a6a7165..d833ed7 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorDetail.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Message/ErrorDetail.cs @@ -4,21 +4,22 @@ namespace RelogicLabs.JsonSchema.Message; public class ErrorDetail { - internal const string InvalidNestedDataType = "Invalid nested data type operation"; + internal const string ValidationFailed = "Validation failed"; + internal const string ValueMismatch = "Value mismatch"; + internal const string DataTypeMismatch = "Data type mismatch"; + internal const string InvalidNestedDataType = "Invalid nested data type"; + internal const string DataTypeArgumentFailed = "Data type argument failed"; internal const string InvalidNestedFunction = "Invalid nested function operation"; internal const string PropertyNotFound = "Mandatory property not found"; internal const string ArrayElementNotFound = "Mandatory array element not found"; internal const string UndefinedPropertyFound = "Undefined property found"; internal const string PropertyKeyMismatch = "Property key mismatch"; internal const string PropertyValueMismatch = "Property value mismatch"; - internal const string DataTypeMismatch = "Data type mismatch"; - internal const string ValidationFailed = "Validation Failed"; - internal const string ValueMismatch = "Value mismatch"; internal const string PropertyOrderMismatch = "Property order mismatch"; public required string Code { get; init; } public required string Message { get; init; } - + [SetsRequiredMembers] public ErrorDetail(string code, string message) { diff --git a/JsonSchema/RelogicLabs/JsonSchema/Message/ExpectedDetail.cs b/JsonSchema/RelogicLabs/JsonSchema/Message/ExpectedDetail.cs index 356216a..dddcf60 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Message/ExpectedDetail.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Message/ExpectedDetail.cs @@ -1,44 +1,46 @@ using System.Diagnostics.CodeAnalysis; using RelogicLabs.JsonSchema.Tree; using RelogicLabs.JsonSchema.Types; -using RelogicLabs.JsonSchema.Utilities; namespace RelogicLabs.JsonSchema.Message; public class ExpectedDetail : ContextDetail { [SetsRequiredMembers] - public ExpectedDetail(Context context, string message) + public ExpectedDetail(Context context, string message) : base(context, message) { } [SetsRequiredMembers] - public ExpectedDetail(JNode node, string message) + public ExpectedDetail(JNode node, string message) : base(node, message) { } - internal static ExpectedDetail AsArrayElementNotFound(JNode node, int index) - => new(node, $"element at {index} ({node.GetOutline()})"); - + internal static ExpectedDetail AsArrayElementNotFound(JNode node, int index) + => new(node, $"element at {index} '{node.GetOutline()}'"); + internal static ExpectedDetail AsValueMismatch(JNode node) => new(node, $"value {node.GetOutline()}"); - + internal static ExpectedDetail AsUndefinedProperty(JObject @object, JProperty property) - => new(@object, $"no property with key {property.Key.Quote()}"); - - internal static ExpectedDetail AsPropertyNotFound(JProperty property) - => new(property, $"property ({property.GetOutline()})"); + => new(@object, $"no property with key '{property.Key}'"); + + internal static ExpectedDetail AsPropertyNotFound(JProperty property) + => new(property, $"property '{property.GetOutline()}'"); - internal static ExpectedDetail AsDataTypeMismatch(JNode node) + internal static ExpectedDetail AsDataTypeMismatch(JNode node) => new(node, $"{GetTypeName(node)} inferred by {node.GetOutline()}"); - - internal static ExpectedDetail AsDataTypeMismatch(JDataType dataType) + + internal static ExpectedDetail AsDataTypeMismatch(JDataType dataType) => new(dataType, $"data type {dataType.ToString(true)}"); - internal static ExpectedDetail AsInvalidFunction(JFunction function) + internal static ExpectedDetail AsInvalidFunction(JFunction function) => new(function, "applying on composite type"); - internal static ExpectedDetail AsInvalidDataType(JDataType dataType) - => new(dataType, "applying on composite type"); + internal static ExpectedDetail AsInvalidNestedDataType(JDataType dataType) + => new(dataType, "composite data type"); + + internal static ExpectedDetail AsDataTypeArgumentFailed(JDataType dataType) + => new(dataType, $"a valid value for '{dataType.Alias}'"); - internal static ExpectedDetail AsPropertyOrderMismatch(JProperty property) - => new(property, $"property with key {property.Key.Quote()} at position"); + internal static ExpectedDetail AsPropertyOrderMismatch(JProperty property) + => new(property, $"property with key '{property.Key}' at current position"); } \ No newline at end of file diff --git a/JsonSchema/RelogicLabs/JsonSchema/Message/MatchReport.cs b/JsonSchema/RelogicLabs/JsonSchema/Message/MatchReport.cs new file mode 100644 index 0000000..643108f --- /dev/null +++ b/JsonSchema/RelogicLabs/JsonSchema/Message/MatchReport.cs @@ -0,0 +1,25 @@ +using static RelogicLabs.JsonSchema.Message.ErrorCode; + +namespace RelogicLabs.JsonSchema.Message; + +internal class MatchReport +{ + public static readonly MatchReport Success = new(); + public static readonly MatchReport TypeError = new(DTYP04, DTYP06); + public static readonly MatchReport ArgumentError = new(DTYP05, DTYP07); + public static readonly MatchReport AliasError = new(DEFI03, DEFI04); + + private readonly string _code1; + private readonly string _code2; + + private MatchReport(string code1, string code2) + { + _code1 = code1; + _code2 = code2; + } + + private MatchReport() : this(string.Empty, string.Empty) { } + + public string GetCode(bool nested) + => nested ? _code2 : _code1; +} \ No newline at end of file diff --git a/JsonSchema/RelogicLabs/JsonSchema/Types/JNode.cs b/JsonSchema/RelogicLabs/JsonSchema/Types/JNode.cs index 1d3daa7..a58a7c0 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Types/JNode.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Types/JNode.cs @@ -59,7 +59,7 @@ public virtual string GetOutline() { if(node is T other) return other; FailWith(new JsonSchemaException( - new ErrorDetail(DTYP03, DataTypeMismatch), + new ErrorDetail(DTYP02, DataTypeMismatch), ExpectedDetail.AsDataTypeMismatch(this), ActualDetail.AsDataTypeMismatch(node))); return default; diff --git a/JsonSchema/RelogicLabs/JsonSchema/Utilities/DebugUtils.cs b/JsonSchema/RelogicLabs/JsonSchema/Utilities/DebugUtils.cs index 33cfaa4..d5025fe 100644 --- a/JsonSchema/RelogicLabs/JsonSchema/Utilities/DebugUtils.cs +++ b/JsonSchema/RelogicLabs/JsonSchema/Utilities/DebugUtils.cs @@ -50,4 +50,4 @@ internal static void Print(Exception exception) if(!DebugPrint) return; Console.Error.WriteLine("[DEBUG] Print of exception: " + exception); } -} +} \ No newline at end of file From cb490993afaa4ed8115246f30b674f630fb3481c Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Wed, 25 Oct 2023 11:57:41 +0600 Subject: [PATCH 3/4] Add new test cases for data types --- .../JsonSchema/Tests/Negative/ArrayTests.cs | 38 ++--- .../JsonSchema/Tests/Negative/BooleanTests.cs | 22 +-- .../Tests/Negative/DataTypeTests.cs | 143 ++++++++++++++++++ .../Tests/Negative/DateTimeTests.cs | 78 +++++----- .../JsonSchema/Tests/Negative/IntegerTests.cs | 46 +++--- .../JsonSchema/Tests/Negative/ObjectTests.cs | 60 ++++---- .../JsonSchema/Tests/Negative/StringTests.cs | 18 +-- .../Tests/Positive/AggregatedTests.cs | 17 +-- 8 files changed, 282 insertions(+), 140 deletions(-) create mode 100644 JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DataTypeTests.cs diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ArrayTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ArrayTests.cs index 07e2f74..aa9b52a 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ArrayTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ArrayTests.cs @@ -11,14 +11,14 @@ public void When_JsonNotArray_ExceptionThrown() { var schema = "#array"; var json = "10"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotArrayInObject_ExceptionThrown() { @@ -38,14 +38,14 @@ public void When_JsonNotArrayInObject_ExceptionThrown() "key3": 100000 } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotArrayInArray_ExceptionThrown() { @@ -57,14 +57,14 @@ public void When_JsonNotArrayInArray_ExceptionThrown() """ [{}, "value1", 10.5] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotArrayInArray_ExceptionThrown() { @@ -76,14 +76,14 @@ public void When_NestedJsonNotArrayInArray_ExceptionThrown() """ [true, "value1", false] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotArrayInObject_ExceptionThrown() { @@ -99,44 +99,44 @@ public void When_NestedJsonNotArrayInObject_ExceptionThrown() "key3": "value1" } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_ElementsWithWrongArray_ExceptionThrown() { var schema = "@elements(10, 20, 30, 40) #array"; var json = "[5, 10, 15, 20, 25]"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(ELEM01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedElementsWithWrongArrayInArray_ExceptionThrown() { var schema = "@elements*(5, 10) #array"; var json = "[[5, 10], [], [5, 10, 15, 20]]"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(ELEM01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_EnumWithWrongValueInArray_ExceptionThrown() { - var schema = + var schema = """ [ @enum(5, 10, 15), @@ -145,27 +145,27 @@ public void When_EnumWithWrongValueInArray_ExceptionThrown() ] #array """; var json = """[11, 102, "efg"]"""; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(ENUM02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidJsonInArray_ExceptionThrown() { var schema = "#array"; var json = "[,,]"; - + //JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(JPRS01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_EmptyArrayInObject_ExceptionThrown() { diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/BooleanTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/BooleanTests.cs index 97630df..0f5db41 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/BooleanTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/BooleanTests.cs @@ -11,27 +11,27 @@ public void When_JsonNotBoolean_ExceptionThrown() { var schema = "#boolean"; var json = "5"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonValueNotEqualForBoolean_ExceptionThrown() { var schema = "true #boolean"; var json = "false"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(BOOL01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotBooleanInObject_ExceptionThrown() { @@ -51,14 +51,14 @@ public void When_JsonNotBooleanInObject_ExceptionThrown() "key3": true } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotBooleanInArray_ExceptionThrown() { @@ -70,14 +70,14 @@ public void When_JsonNotBooleanInArray_ExceptionThrown() """ [[], 11.5, "false"] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotBooleanInArray_ExceptionThrown() { @@ -89,14 +89,14 @@ public void When_NestedJsonNotBooleanInArray_ExceptionThrown() """ ["true", {}, [true]] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotBooleanInObject_ExceptionThrown() { @@ -112,7 +112,7 @@ public void When_NestedJsonNotBooleanInObject_ExceptionThrown() "key3": false } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DataTypeTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DataTypeTests.cs new file mode 100644 index 0000000..f50495f --- /dev/null +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DataTypeTests.cs @@ -0,0 +1,143 @@ +using RelogicLabs.JsonSchema.Exceptions; +using static RelogicLabs.JsonSchema.Message.ErrorCode; + +namespace RelogicLabs.JsonSchema.Tests.Negative; + +[TestClass] +public class DataTypeTests +{ + [TestMethod] + public void When_JsonWithWrongMainDataType_ExceptionThrown() + { + var schema = + """ + #string* #array + """; + var json = + """ + 10 + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DTYP04, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_JsonWithWrongNestedDataType_ExceptionThrown() + { + var schema = + """ + #string* #array + """; + var json = + """ + [10, 20] + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DTYP06, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_NestedTypeWithNonCompositeJson_ExceptionThrown() + { + var schema = + """ + #string* + """; + var json = + """ + 10 + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DTYP03, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_UndefinedDataTypeArgument_ExceptionThrown() + { + var schema = + """ + #array($undefined) + """; + var json = + """ + [10, 20] + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DEFI03, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_UndefinedNestedDataTypeArgument_ExceptionThrown() + { + var schema = + """ + #integer*($undefined) #array + """; + var json = + """ + [10, 20] + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DEFI04, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_DataTypeArgumentWithValidationFailed_ExceptionThrown() + { + var schema = + """ + %define $test: {"k1": #string} + %schema: #object($test) + """; + var json = + """ + {"k1": 10} + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DTYP04, exception.Code); + Console.WriteLine(exception); + } + + [TestMethod] + public void When_NestedDataTypeArgumentWithValidationFailed_ExceptionThrown() + { + var schema = + """ + %define $test: {"k1": #string} + %schema: #object*($test) #array + """; + var json = + """ + [{"k1": 10}] + """; + + JsonSchema.IsValid(schema, json); + var exception = Assert.ThrowsException( + () => JsonAssert.IsValid(schema, json)); + Assert.AreEqual(DTYP04, exception.Code); + Console.WriteLine(exception); + } +} \ No newline at end of file diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DateTimeTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DateTimeTests.cs index d0b8f5b..80a41ca 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DateTimeTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/DateTimeTests.cs @@ -11,27 +11,27 @@ public void When_JsonNotDate_ExceptionThrown() { var schema = "#date"; var json = "\"This is not a valid date\""; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotTime_ExceptionThrown() { var schema = "#time"; var json = "\"This is not a valid time\""; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_DateInputWrong_ExceptionThrown() { @@ -43,7 +43,7 @@ public void When_DateInputWrong_ExceptionThrown() Assert.AreEqual(DDAY04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_TimeInputWrong_ExceptionThrown() { @@ -55,7 +55,7 @@ public void When_TimeInputWrong_ExceptionThrown() Assert.AreEqual(DHUR03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_DateDayOutOfRange_ExceptionThrown() { @@ -67,7 +67,7 @@ public void When_DateDayOutOfRange_ExceptionThrown() Assert.AreEqual(DDAY03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_DateDayOutOfRange2_ExceptionThrown() { @@ -79,7 +79,7 @@ public void When_DateDayOutOfRange2_ExceptionThrown() Assert.AreEqual(DDAY04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateMonthFullName_ExceptionThrown() { @@ -91,7 +91,7 @@ public void When_InvalidDateMonthFullName_ExceptionThrown() Assert.AreEqual(DMON01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateMonthShortName_ExceptionThrown() { @@ -103,7 +103,7 @@ public void When_InvalidDateMonthShortName_ExceptionThrown() Assert.AreEqual(DMON02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateMonthNumber_ExceptionThrown() { @@ -115,7 +115,7 @@ public void When_InvalidDateMonthNumber_ExceptionThrown() Assert.AreEqual(DMON03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateMonthNumberRange_ExceptionThrown() { @@ -127,7 +127,7 @@ public void When_InvalidDateMonthNumberRange_ExceptionThrown() Assert.AreEqual(DMON05, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateWeekdayInput_ExceptionThrown() { @@ -139,7 +139,7 @@ public void When_InvalidDateWeekdayInput_ExceptionThrown() Assert.AreEqual(DWKD02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_ConflictingDateInfoInInput_ExceptionThrown() { @@ -151,7 +151,7 @@ public void When_ConflictingDateInfoInInput_ExceptionThrown() Assert.AreEqual(DCNF01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_ConflictingTimeInfoInInput_ExceptionThrown() { @@ -163,7 +163,7 @@ public void When_ConflictingTimeInfoInInput_ExceptionThrown() Assert.AreEqual(DCNF01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateWeekday_ExceptionThrown() { @@ -175,7 +175,7 @@ public void When_InvalidDateWeekday_ExceptionThrown() Assert.AreEqual(DWKD03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateYearInput_ExceptionThrown() { @@ -187,7 +187,7 @@ public void When_InvalidDateYearInput_ExceptionThrown() Assert.AreEqual(DYAR02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateYearInput2_ExceptionThrown() { @@ -199,7 +199,7 @@ public void When_InvalidDateYearInput2_ExceptionThrown() Assert.AreEqual(DYAR03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateYearInput3_ExceptionThrown() { @@ -211,7 +211,7 @@ public void When_InvalidDateYearInput3_ExceptionThrown() Assert.AreEqual(DINV02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDateEraInput_ExceptionThrown() { @@ -223,7 +223,7 @@ public void When_InvalidDateEraInput_ExceptionThrown() Assert.AreEqual(DERA01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeTextMissing_ExceptionThrown() { @@ -235,7 +235,7 @@ public void When_InvalidTimeTextMissing_ExceptionThrown() Assert.AreEqual(DTXT01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeHourInput_ExceptionThrown() { @@ -247,7 +247,7 @@ public void When_InvalidTimeHourInput_ExceptionThrown() Assert.AreEqual(DHUR01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeHourRange_ExceptionThrown() { @@ -259,7 +259,7 @@ public void When_InvalidTimeHourRange_ExceptionThrown() Assert.AreEqual(DHUR06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeMinuteInput_ExceptionThrown() { @@ -271,7 +271,7 @@ public void When_InvalidTimeMinuteInput_ExceptionThrown() Assert.AreEqual(DMIN01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeMinuteRange_ExceptionThrown() { @@ -283,7 +283,7 @@ public void When_InvalidTimeMinuteRange_ExceptionThrown() Assert.AreEqual(DMIN03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeSecondInput_ExceptionThrown() { @@ -295,7 +295,7 @@ public void When_InvalidTimeSecondInput_ExceptionThrown() Assert.AreEqual(DSEC01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeSecondRange_ExceptionThrown() { @@ -307,7 +307,7 @@ public void When_InvalidTimeSecondRange_ExceptionThrown() Assert.AreEqual(DSEC03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeSecondFraction_ExceptionThrown() { @@ -319,7 +319,7 @@ public void When_InvalidTimeSecondFraction_ExceptionThrown() Assert.AreEqual(DFRC04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeNoHourInput_ExceptionThrown() { @@ -331,7 +331,7 @@ public void When_InvalidTimeNoHourInput_ExceptionThrown() Assert.AreEqual(DHUR02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeInput_ExceptionThrown() { @@ -343,7 +343,7 @@ public void When_InvalidTimeInput_ExceptionThrown() Assert.AreEqual(DWTS01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeAmPmInput_ExceptionThrown() { @@ -355,7 +355,7 @@ public void When_InvalidTimeAmPmInput_ExceptionThrown() Assert.AreEqual(DTAP01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTime12HourInput_ExceptionThrown() { @@ -367,7 +367,7 @@ public void When_InvalidTime12HourInput_ExceptionThrown() Assert.AreEqual(DHUR03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeAmPmMissing_ExceptionThrown() { @@ -379,7 +379,7 @@ public void When_InvalidTimeAmPmMissing_ExceptionThrown() Assert.AreEqual(DTAP01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeUTCOffsetInput_ExceptionThrown() { @@ -391,7 +391,7 @@ public void When_InvalidTimeUTCOffsetInput_ExceptionThrown() Assert.AreEqual(DUTC01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeUTCOffsetHourRange_ExceptionThrown() { @@ -403,7 +403,7 @@ public void When_InvalidTimeUTCOffsetHourRange_ExceptionThrown() Assert.AreEqual(DUTC04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimeUTCOffsetMinuteRange_ExceptionThrown() { @@ -415,26 +415,26 @@ public void When_InvalidTimeUTCOffsetMinuteRange_ExceptionThrown() Assert.AreEqual(DUTC05, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidDatePatternCauseLexerError_ExceptionThrown() { var schema = """ @date("ABCD") """; var json = "\"23-09-01T14:35:10.555\""; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DLEX01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidTimePatternCauseLexerError_ExceptionThrown() { var schema = """ @time("ABCD") """; var json = "\"23-09-01T14:35:10.555\""; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/IntegerTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/IntegerTests.cs index cf55d61..655d15b 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/IntegerTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/IntegerTests.cs @@ -11,27 +11,27 @@ public void When_JsonNotInteger_ExceptionThrown() { var schema = "#integer"; var json = "10.5"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonValueNotEqualForInteger_ExceptionThrown() { var schema = "10 #integer"; var json = "9"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(INTE01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotIntegerInObject_ExceptionThrown() { @@ -51,14 +51,14 @@ public void When_JsonNotIntegerInObject_ExceptionThrown() "key3": 4000.45 } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotIntegerInArray_ExceptionThrown() { @@ -70,14 +70,14 @@ public void When_JsonNotIntegerInArray_ExceptionThrown() """ [true, -4568.57, 100] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotIntegerInArray_ExceptionThrown() { @@ -89,14 +89,14 @@ public void When_NestedJsonNotIntegerInArray_ExceptionThrown() """ [null, 2.2, "40000000"] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotIntegerInObject_ExceptionThrown() { @@ -112,14 +112,14 @@ public void When_NestedJsonNotIntegerInObject_ExceptionThrown() "key3": "-50000" } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedRangeWithJsonNotIntegerInObject_ExceptionThrown() { @@ -135,14 +135,14 @@ public void When_NestedRangeWithJsonNotIntegerInObject_ExceptionThrown() "key3": "-50000" } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedRangeWithNonCompositeJsonInObject_ExceptionThrown() { @@ -154,14 +154,14 @@ public void When_NestedRangeWithNonCompositeJsonInObject_ExceptionThrown() """ "value1" """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(FUNC06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedRangeWithJsonWrongIntegerInObject_ExceptionThrown() { @@ -177,14 +177,14 @@ public void When_NestedRangeWithJsonWrongIntegerInObject_ExceptionThrown() "key3": -500 } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(RANG01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedRangeWithUndefinedAndWrongIntegerInArray_ExceptionThrown() { @@ -196,14 +196,14 @@ public void When_NestedRangeWithUndefinedAndWrongIntegerInArray_ExceptionThrown( """ [100, 500, 900] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(RANG04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedPositiveWithWrongIntegerInArray_ExceptionThrown() { @@ -215,14 +215,14 @@ public void When_NestedPositiveWithWrongIntegerInArray_ExceptionThrown() """ [100, -500, 900] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(POSI01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedNegativeWithWrongIntegerInArray_ExceptionThrown() { @@ -234,7 +234,7 @@ public void When_NestedNegativeWithWrongIntegerInArray_ExceptionThrown() """ [-100, -500, 900] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ObjectTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ObjectTests.cs index c781c69..0bfa568 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ObjectTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/ObjectTests.cs @@ -11,14 +11,14 @@ public void When_JsonNotObject_ExceptionThrown() { var schema = "#object"; var json = "100"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotObjectInObject_ExceptionThrown() { @@ -38,14 +38,14 @@ public void When_JsonNotObjectInObject_ExceptionThrown() "key3": [10, 20, 30] } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotObjectInArray_ExceptionThrown() { @@ -57,14 +57,14 @@ public void When_JsonNotObjectInArray_ExceptionThrown() """ [null, "value1", true] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotObjectInArray_ExceptionThrown() { @@ -76,14 +76,14 @@ public void When_NestedJsonNotObjectInArray_ExceptionThrown() """ [ 100, true, false ] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedJsonNotObjectInObject_ExceptionThrown() { @@ -99,14 +99,14 @@ public void When_NestedJsonNotObjectInObject_ExceptionThrown() "key3": [10] } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP06, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_KeysWithWrongObject_ExceptionThrown() { @@ -122,14 +122,14 @@ public void When_KeysWithWrongObject_ExceptionThrown() "key6": 200 } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(KEYS01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_ValuesWithWrongObject_ExceptionThrown() { @@ -145,14 +145,14 @@ public void When_ValuesWithWrongObject_ExceptionThrown() "key3": 3 } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(VALU01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedKeysWithWrongObjectInObject_ExceptionThrown() { @@ -168,14 +168,14 @@ public void When_NestedKeysWithWrongObjectInObject_ExceptionThrown() "key3": {"value": 1000} } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(KEYS01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_NestedKeysAndValuesWithWrongObjectInArray_ExceptionThrown() { @@ -187,18 +187,18 @@ public void When_NestedKeysAndValuesWithWrongObjectInArray_ExceptionThrown() """ [{"value": 10}, {"value": 20}, {"value": 30}] """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(KEYS01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_EnumWithWrongObject_ExceptionThrown() { - var schema = + var schema = """ { "key1": @enum(5, 10, 15), @@ -206,7 +206,7 @@ public void When_EnumWithWrongObject_ExceptionThrown() "key3": @enum("abc", "pqr", "xyz") } #object """; - var json = + var json = """ { "key1": 1, @@ -214,14 +214,14 @@ public void When_EnumWithWrongObject_ExceptionThrown() "key3": "efg" } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(ENUM02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_DuplicateJsonPropertyInObject_ExceptionThrown() { @@ -241,14 +241,14 @@ public void When_DuplicateJsonPropertyInObject_ExceptionThrown() "key2": [10, 20, 30] } """; - + //JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(PROP03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_DuplicateSchemaPropertyInObject_ExceptionThrown() { @@ -268,14 +268,14 @@ public void When_DuplicateSchemaPropertyInObject_ExceptionThrown() "key3": [10, 20, 30] } """; - + //JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(PROP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_EmptyObjectInArray_ExceptionThrown() { @@ -299,7 +299,7 @@ public void When_EmptyObjectInArray_ExceptionThrown() Assert.AreEqual(NEMT03, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_WrongLengthOfObjectInArray1_ExceptionThrown() { @@ -321,7 +321,7 @@ public void When_WrongLengthOfObjectInArray1_ExceptionThrown() Assert.AreEqual(OLEN01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_WrongLengthOfObjectInArray2_ExceptionThrown() { @@ -343,7 +343,7 @@ public void When_WrongLengthOfObjectInArray2_ExceptionThrown() Assert.AreEqual(OLEN02, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_WrongLengthOfObjectInArray3_ExceptionThrown() { @@ -365,7 +365,7 @@ public void When_WrongLengthOfObjectInArray3_ExceptionThrown() Assert.AreEqual(OLEN05, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_WrongLengthOfObjectInArray4_ExceptionThrown() { diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/StringTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/StringTests.cs index 6a8229f..bf20966 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/StringTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Negative/StringTests.cs @@ -11,26 +11,26 @@ public void When_JsonNotString_ExceptionThrown() { var schema = "#string"; var json = "10"; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidUnicodeStringInSchema_ExceptionThrown() { var schema = @"""\uX0485\uY486\r\n\t #string"""; var json = @"""\u0485\u0486\r\n\t"""; - + var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); Assert.AreEqual(SLEX01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_InvalidUnicodeStringInJson_ExceptionThrown() { @@ -42,7 +42,7 @@ public void When_InvalidUnicodeStringInJson_ExceptionThrown() Assert.AreEqual(JLEX01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotStringInObject_ExceptionThrown() { @@ -68,7 +68,7 @@ public void When_JsonNotStringInObject_ExceptionThrown() Assert.AreEqual(DTYP04, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_JsonNotStringInArray_ExceptionThrown() { @@ -283,7 +283,7 @@ public void When_UrlWithWrongStringAddressInObject_ExceptionThrown() Assert.AreEqual(URLA01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_UrlWithSchemeAndWrongStringAddressInObject_ExceptionThrown() { @@ -301,7 +301,7 @@ public void When_UrlWithSchemeAndWrongStringAddressInObject_ExceptionThrown() "key2": "ftp://www.example.com/" } """; - + JsonSchema.IsValid(schema, json); var exception = Assert.ThrowsException( () => JsonAssert.IsValid(schema, json)); @@ -334,7 +334,7 @@ public void When_PhoneWithWrongStringInObject_ExceptionThrown() Assert.AreEqual(PHON01, exception.Code); Console.WriteLine(exception); } - + [TestMethod] public void When_EmptyStringInObject_ExceptionThrown() { diff --git a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Positive/AggregatedTests.cs b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Positive/AggregatedTests.cs index 189672d..573eae2 100644 --- a/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Positive/AggregatedTests.cs +++ b/JsonSchema.Tests/RelogicLabs/JsonSchema/Tests/Positive/AggregatedTests.cs @@ -186,7 +186,7 @@ public void When_ExtendedJsonSchemaAggregatedTest_ValidTrue() "storage": @regex("[0-9]{1,4}GB (SSD|HDD)") #string } #object #null } - %define $tags: @length(1, 10) #array($tag) + %define $tags: @length(1, 10) #string*($tag) #array %define $tag: @length(3, 20) @regex("[A-Za-z_]+") #string %schema: { @@ -194,10 +194,9 @@ public void When_ExtendedJsonSchemaAggregatedTest_ValidTrue() "id": @range(1, 10000) #integer, /*username does not allow special characters*/ "username": @regex("[a-z_]{3,30}") #string, - /*currently only one role is allowed by system*/ - "role": "user" #string, + "role": @enum("user", "admin") #string, "isActive": #boolean, //user account current status - "registeredAt": #time, + "registeredAt": @time("DD-MM-YYYY hh:mm:ss") #string, "profile": { "firstName": @regex("[A-Za-z]{3,50}") #string, "lastName": @regex("[A-Za-z]{3,50}") #string, @@ -231,9 +230,9 @@ public void When_ExtendedJsonSchemaAggregatedTest_ValidTrue() "user": { "id": 1234, "username": "johndoe", - "role": "user", + "role": "admin", "isActive": true, - "registeredAt": "2023-09-06T15:10:30.639Z", + "registeredAt": "06-09-2023 15:10:30", "profile": { "firstName": "John", "lastName": "Doe", @@ -301,9 +300,9 @@ public void When_ExtendedJsonSchemaAggregatedTest_ValidTrue() "price": 1299.99, "inStock": false, "specs": { - "cpu": "Intel i7", - "ram": "16GB", - "storage": "512GB SSD" + "cpu": "Intel i11", + "ram": "11GB", + "storage": "11GB SSD" } } ], From ad6a762116cf2a016b3098b855aa45f91dd504ce Mon Sep 17 00:00:00 2001 From: Zahid Hossain <60911932+zhossain-info@users.noreply.github.com> Date: Wed, 25 Oct 2023 12:23:55 +0600 Subject: [PATCH 4/4] Update project documentations --- ...icLabs.JsonSchema.Message.ErrorDetail.html | 6 +-- ...abs.JsonSchema.Message.ExpectedDetail.html | 8 ++-- ...icLabs.JsonSchema.Tree.RuntimeContext.html | 24 +++++----- ...elogicLabs.JsonSchema.Types.JDataType.html | 24 +++++----- ...logicLabs.JsonSchema.Types.JValidator.html | 2 +- JsonSchema/docs/articles/intro.md | 2 +- JsonSchema/docs/articles/quickstart.html | 15 +++--- JsonSchema/docs/articles/quickstart.md | 20 +++----- JsonSchema/docs/articles/sourcebuild.html | 40 +++++++++++++--- JsonSchema/docs/articles/sourcebuild.md | 46 +++++++++++++++---- JsonSchema/docs/index.html | 19 ++++---- JsonSchema/docs/index.json | 6 +-- JsonSchema/docs/index.md | 21 ++++----- 13 files changed, 138 insertions(+), 95 deletions(-) diff --git a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ErrorDetail.html b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ErrorDetail.html index f19b421..33b8f11 100644 --- a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ErrorDetail.html +++ b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ErrorDetail.html @@ -150,7 +150,7 @@

Constructors

ErrorDetail(string, string) - +

@@ -187,7 +187,7 @@

Properties

Code - +

@@ -218,7 +218,7 @@

Property Value

Message - +

diff --git a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ExpectedDetail.html b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ExpectedDetail.html index d15a104..a37575e 100644 --- a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ExpectedDetail.html +++ b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Message.ExpectedDetail.html @@ -83,7 +83,7 @@
Table of Contents

Class ExpectedDetail - +

@@ -160,7 +160,7 @@

Constructors

ExpectedDetail(Context, string) - +

@@ -193,7 +193,7 @@

Parameters

ExpectedDetail(JNode, string) - +

@@ -226,7 +226,7 @@

Parameters

diff --git a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Tree.RuntimeContext.html b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Tree.RuntimeContext.html index b32dc61..c77f092 100644 --- a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Tree.RuntimeContext.html +++ b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Tree.RuntimeContext.html @@ -150,7 +150,7 @@

Properties

Definitions - +

@@ -181,7 +181,7 @@

Property Value

Exceptions - +

@@ -212,7 +212,7 @@

Property Value

FloatingPointTolerance - +

@@ -243,7 +243,7 @@

Property Value

IgnoreObjectPropertyOrder - +

@@ -274,7 +274,7 @@

Property Value

IgnoreUndefinedProperties - +

@@ -305,7 +305,7 @@

Property Value

ThrowException - +

@@ -340,7 +340,7 @@

Methods

AddClass(JInclude) - +

@@ -376,7 +376,7 @@

Returns

AddClass(string, Context?) - +

@@ -409,7 +409,7 @@

Parameters

AddDefinition(JDefinition) - +

@@ -445,7 +445,7 @@

Returns

AddPragma(JPragma) - +

@@ -481,7 +481,7 @@

Returns

GetPragmaValue<T>(string) - +

@@ -522,7 +522,7 @@

Type Parameters

InvokeFunction(JFunction, JNode) - +

diff --git a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JDataType.html b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JDataType.html index 024034d..910fe8f 100644 --- a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JDataType.html +++ b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JDataType.html @@ -83,7 +83,7 @@
Table of Contents

Class JDataType - +

@@ -170,7 +170,7 @@

Properties

Alias - +

@@ -201,7 +201,7 @@

Property Value

Children - +

@@ -232,7 +232,7 @@

Property Value

JsonType - +

@@ -263,7 +263,7 @@

Property Value

Nested - +

@@ -298,7 +298,7 @@

Methods

Equals(object?) - +

Determines whether the specified object is equal to the current object.

@@ -337,7 +337,7 @@

Returns

GetHashCode() - +

Serves as the default hash function.

@@ -370,7 +370,7 @@

Returns

IsApplicable(JNode) - +

@@ -406,7 +406,7 @@

Returns

Match(JNode) - +

Determines whether the specified node matches with the current node.

@@ -446,7 +446,7 @@

Returns

ToString() - +

Returns a JSON string that represents the current object.

@@ -479,7 +479,7 @@

Returns

ToString(bool) - +

@@ -515,7 +515,7 @@

Returns

diff --git a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JValidator.html b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JValidator.html index 7aab281..f0307a7 100644 --- a/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JValidator.html +++ b/JsonSchema/docs/api/RelogicLabs.JsonSchema.Types.JValidator.html @@ -403,7 +403,7 @@

Returns

ToString() - +

Returns a JSON string that represents the current object.

diff --git a/JsonSchema/docs/articles/intro.md b/JsonSchema/docs/articles/intro.md index d4fd3bb..d2b636b 100644 --- a/JsonSchema/docs/articles/intro.md +++ b/JsonSchema/docs/articles/intro.md @@ -21,4 +21,4 @@ JSON, short for JavaScript Object Notation, is one of the most widely used data * [API Reference Documentation](/JsonSchema-DotNet/api/index.html) -
+
\ No newline at end of file diff --git a/JsonSchema/docs/articles/quickstart.html b/JsonSchema/docs/articles/quickstart.html index 2d3e2b4..9a5c281 100644 --- a/JsonSchema/docs/articles/quickstart.html +++ b/JsonSchema/docs/articles/quickstart.html @@ -76,11 +76,8 @@
Table of Contents
- -

Getting Started

+

This guide will walk you through the essential steps to quickly get up and running with New JSON Schema library. It is also assumes a modest familiarity with the .NET SDK and .NET CLI (command-line interface) toolchain including basic familiarity with NuGet packages. Additionally, it considers a certain level of knowledge in C# language.

NuGet Library Package

To get started, launch your preferred IDE (such as Visual Studio, JetBrains Rider, or VS Code) and open the C# project where you intend to include this library package. Within your IDE, navigate to the NuGet package manager and search for the package by the name 'RelogicLabs.JsonSchema'. Subsequently, proceed to add or install the package to your project. Alternatively, you can use the .NET CLI to add the package to your project. Simply run the following command, replacing 1.x.x with either the latest version or your preferred version:

@@ -91,6 +88,7 @@

NuGet Library Package

<PackageReference Include="RelogicLabs.JsonSchema" Version="1.x.x" /> </ItemGroup> +

For additional information regarding this library package, you can visit the NuGet package repository page of this library here.

Write a Sample to Test

With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema.

using RelogicLabs.JsonSchema;
@@ -157,8 +155,7 @@ 

Write a Sample to Test

} }
-

For more information about the schema syntax format and library functionalities, please refer to the reference documentation here.

-

Create Some Validation Errors

+

Create Validation Errors

Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors.

{
     "user": {
@@ -196,7 +193,8 @@ 

Create Some Validation Errors

Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "profile"...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": "Doe", "a...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}.
-

To utilize this library for test automation and API testing, you can employ the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors:

+

Assertion for Validation

+

To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors:

...
 
 try {
@@ -207,7 +205,7 @@ 

Create Some Validation Errors

...
-

The following presents the printed stack trace for the preceding example. It's important to note that when utilizing JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema:

+

The following presents the printed stack trace for the preceding example. It's important to note that when using JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema:

RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch
 Expected (Schema Line: 6:31): data type #integer
 Actual (Json Line: 3:14): found #string inferred by "not number"
@@ -225,7 +223,6 @@ 

Create Some Validation Errors

at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 -

For more information about the schema syntax format and library functionalities, please refer to the reference documentation here.

diff --git a/JsonSchema/docs/articles/quickstart.md b/JsonSchema/docs/articles/quickstart.md index 47367f4..2ea1088 100644 --- a/JsonSchema/docs/articles/quickstart.md +++ b/JsonSchema/docs/articles/quickstart.md @@ -1,7 +1,3 @@ - - # Getting Started This guide will walk you through the essential steps to quickly get up and running with New JSON Schema library. It is also assumes a modest familiarity with the .NET SDK and .NET CLI (command-line interface) toolchain including basic familiarity with NuGet packages. Additionally, it considers a certain level of knowledge in C# language. @@ -16,6 +12,8 @@ To verify the successful integration of the library into your project, you may m ``` +For additional information regarding this library package, you can visit the NuGet package repository page of this library [here](https://www.nuget.org/packages/RelogicLabs.JsonSchema). + ## Write a Sample to Test With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema. ```c# @@ -83,9 +81,8 @@ public class SampleSchema } } ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). -## Create Some Validation Errors +## Create Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the `id` within the `user` object to a string type and observe the outcome. Additionally, we'll modify the `username` by inserting a space into its value, thus creating an invalid `username`. Below is the revised JSON representation, now containing these purposeful errors. ```json { @@ -109,7 +106,6 @@ Let's intentionally introduce a few errors by modifying the previous JSON docume } } ``` - To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the `WriteError` method to display the errors if validation fails is as follows: ```c# @@ -120,7 +116,6 @@ if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... ``` - Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. ```accesslog @@ -131,8 +126,8 @@ Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. ``` -To utilize this library for test automation and API testing, you can employ the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: - +## Assertion for Validation +To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: ```c# ... @@ -144,8 +139,7 @@ try { ... ``` -The following presents the printed stack trace for the preceding example. It's important to note that when utilizing `JsonAssert`, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: - +The following presents the printed stack trace for the preceding example. It's important to note that when using `JsonAssert`, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: ```accesslog RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch Expected (Schema Line: 6:31): data type #integer @@ -164,7 +158,5 @@ Actual (Json Line: 3:14): found #string inferred by "not number" at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 - ``` - For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). \ No newline at end of file diff --git a/JsonSchema/docs/articles/sourcebuild.html b/JsonSchema/docs/articles/sourcebuild.html index 454446f..6b741cd 100644 --- a/JsonSchema/docs/articles/sourcebuild.html +++ b/JsonSchema/docs/articles/sourcebuild.html @@ -76,11 +76,8 @@
Table of Contents
- -

Build from Source Code

+

This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. Within this document, we will navigate through these steps, presenting them clearly and straightforwardly.

Build the Library

To get started, clone the project from the following URL using your preferred Git client (command line or GUI). You can open a terminal and enter the following Git clone command as shown below:

@@ -164,8 +161,7 @@

Write a Sample to Test

} } -

For more information about the schema syntax format and library functionalities, please refer to the reference documentation here.

-

Create Some Validation Errors

+

Create Validation Errors

Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors.

{
     "user": {
@@ -203,6 +199,38 @@ 

Create Some Validation Errors

Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "profile"...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": "Doe", "a...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}.
+

Assertion for Validation

+

To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors:

+
...
+
+try {
+    JsonAssert.IsValid(schema, json);
+} catch(Exception e) {
+    Console.Error.WriteLine(e);
+}
+
+...
+
+

The following presents the printed stack trace for the preceding example. It's important to note that when using JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema:

+
RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch
+Expected (Schema Line: 6:31): data type #integer
+Actual (Json Line: 3:14): found #string inferred by "not number"
+
+   at RelogicLabs.JsonSchema.Tree.RuntimeContext.FailWith(Exception exception)
+   at RelogicLabs.JsonSchema.Types.JNode.FailWith(Exception exception)
+   at RelogicLabs.JsonSchema.Types.JDataType.MatchForReport(JNode node)
+   at RelogicLabs.JsonSchema.Types.JValidator.<>c__DisplayClass22_0.<Match>b__1(JDataType d)
+   at RelogicLabs.JsonSchema.Utilities.CollectionExtension.ForEach[T](IEnumerable`1 enumeration, Action`1 action)
+   at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node)
+   at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node)
+   at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node)
+   at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node)
+   at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node)
+   at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node)
+   at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual)
+   at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61
+
+

For more information about the schema syntax format and library functionalities, please refer to the reference documentation here.

diff --git a/JsonSchema/docs/articles/sourcebuild.md b/JsonSchema/docs/articles/sourcebuild.md index 776f8fb..271aa31 100644 --- a/JsonSchema/docs/articles/sourcebuild.md +++ b/JsonSchema/docs/articles/sourcebuild.md @@ -1,7 +1,3 @@ - - # Build from Source Code This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. Within this document, we will navigate through these steps, presenting them clearly and straightforwardly. @@ -92,9 +88,8 @@ public class SampleSchema } } ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). -## Create Some Validation Errors +## Create Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the `id` within the `user` object to a string type and observe the outcome. Additionally, we'll modify the `username` by inserting a space into its value, thus creating an invalid `username`. Below is the revised JSON representation, now containing these purposeful errors. ```json { @@ -118,7 +113,6 @@ Let's intentionally introduce a few errors by modifying the previous JSON docume } } ``` - To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the `WriteError` method to display the errors if validation fails is as follows: ```c# @@ -129,7 +123,6 @@ if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... ``` - Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. ```accesslog @@ -138,4 +131,39 @@ Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern "[a-z_]{3,30}" is expected but found "john doe" that mismatches with pattern. Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, "profile"...ing, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}} is expected but found {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": "Doe", "a...: "123 Some St", "city": "Some town", "country": "Some Country"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {"user": {"id": @range(1, 10000) #integer, "username": @regex("[a-z_]{3,30}") #string, "role": "user" #string, "isActive": #boolean, ...ng, "country": @regex("[A-Za-z ]{3,50}") #string} #object #null}}} is expected but found {"user": {"id": "not number", "username": "john doe", "role": "user", "isActive": true, "profile": {"firstName": "John", "lastName": ... "123 Some St", "city": "Some town", "country": "Some Country"}}}}. -``` \ No newline at end of file +``` + +## Assertion for Validation +To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: +```c# +... + +try { + JsonAssert.IsValid(schema, json); +} catch(Exception e) { + Console.Error.WriteLine(e); +} + +... +``` +The following presents the printed stack trace for the preceding example. It's important to note that when using `JsonAssert`, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: +```accesslog +RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch +Expected (Schema Line: 6:31): data type #integer +Actual (Json Line: 3:14): found #string inferred by "not number" + + at RelogicLabs.JsonSchema.Tree.RuntimeContext.FailWith(Exception exception) + at RelogicLabs.JsonSchema.Types.JNode.FailWith(Exception exception) + at RelogicLabs.JsonSchema.Types.JDataType.MatchForReport(JNode node) + at RelogicLabs.JsonSchema.Types.JValidator.<>c__DisplayClass22_0.b__1(JDataType d) + at RelogicLabs.JsonSchema.Utilities.CollectionExtension.ForEach[T](IEnumerable`1 enumeration, Action`1 action) + at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) + at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) + at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) + at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) + at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) + at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) + at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) + at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 +``` +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). \ No newline at end of file diff --git a/JsonSchema/docs/index.html b/JsonSchema/docs/index.html index 070adb4..3002045 100644 --- a/JsonSchema/docs/index.html +++ b/JsonSchema/docs/index.html @@ -144,7 +144,7 @@

Extended Example

%title: "Extended User Profile Dashboard API Response"
 %version: 2.0.0
 %include: RelogicLabs.JsonSchema.Tests.Positive.ExternalFunctions,
-            RelogicLabs.JsonSchema.Tests
+          RelogicLabs.JsonSchema.Tests
 
 %pragma IgnoreUndefinedProperties: true
 
@@ -168,7 +168,7 @@ 

Extended Example

} #object #null } -%define $tags: @length(1, 10) #array($tag) +%define $tags: @length(1, 10) #string*($tag) #array %define $tag: @length(3, 20) @regex("[A-Za-z_]+") #string %schema: @@ -177,10 +177,9 @@

Extended Example

"id": @range(1, 10000) #integer, /*username does not allow special characters*/ "username": @regex("[a-z_]{3,30}") #string, - /*currently only one role is allowed by system*/ - "role": "user" #string, + "role": @enum("user", "admin") #string, "isActive": #boolean, //user account current status - "registeredAt": #time, + "registeredAt": @time("DD-MM-YYYY hh:mm:ss") #string, "profile": { "firstName": @regex("[A-Za-z]{3,50}") #string, "lastName": @regex("[A-Za-z]{3,50}") #string, @@ -214,9 +213,9 @@

Extended Example

"user": { "id": 1234, "username": "johndoe", - "role": "user", + "role": "admin", "isActive": true, - "registeredAt": "2023-09-06T15:10:30.639Z", + "registeredAt": "06-09-2023 15:10:30", "profile": { "firstName": "John", "lastName": "Doe", @@ -284,9 +283,9 @@

Extended Example

"price": 1299.99, "inStock": false, "specs": { - "cpu": "Intel i7", - "ram": "16GB", - "storage": "512GB SSD" + "cpu": "Intel i11", + "ram": "11GB", + "storage": "11GB SSD" } } ], diff --git a/JsonSchema/docs/index.json b/JsonSchema/docs/index.json index 98f690b..c35f8d4 100644 --- a/JsonSchema/docs/index.json +++ b/JsonSchema/docs/index.json @@ -417,12 +417,12 @@ "articles/quickstart.html": { "href": "articles/quickstart.html", "title": "Getting Started | Json Schema", - "keywords": "pre code { font-size: 1.1em; } Getting Started This guide will walk you through the essential steps to quickly get up and running with New JSON Schema library. It is also assumes a modest familiarity with the .NET SDK and .NET CLI (command-line interface) toolchain including basic familiarity with NuGet packages. Additionally, it considers a certain level of knowledge in C# language. NuGet Library Package To get started, launch your preferred IDE (such as Visual Studio, JetBrains Rider, or VS Code) and open the C# project where you intend to include this library package. Within your IDE, navigate to the NuGet package manager and search for the package by the name 'RelogicLabs.JsonSchema'. Subsequently, proceed to add or install the package to your project. Alternatively, you can use the .NET CLI to add the package to your project. Simply run the following command, replacing 1.x.x with either the latest version or your preferred version: dotnet add package RelogicLabs.JsonSchema --version 1.x.x To verify the successful integration of the library into your project, you may manually inspect your project file, typically named .csproj, using a text editor, and search for the following XML snippet within the file: Write a Sample to Test With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema. using RelogicLabs.JsonSchema; namespace CSharpApplication; public class SampleSchema { public bool CheckIsValid() { var schema = \"\"\" %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } \"\"\"; var json = \"\"\" { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } \"\"\"; JsonSchema jsonSchema = new(schema); return jsonSchema.IsValid(json); } } For more information about the schema syntax format and library functionalities, please refer to the reference documentation here. Create Some Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors. { \"user\": { \"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the WriteError method to display the errors if validation fails is as follows: ... JsonSchema jsonSchema = new(schema); if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by \"not number\". Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of \"not number\" Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern \"[a-z_]{3,30}\" is expected but found \"john doe\" that mismatches with pattern. Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, \"profile\"...ing, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}} is expected but found {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": \"Doe\", \"a...: \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {\"user\": {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, ...ng, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}}} is expected but found {\"user\": {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": ... \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}}. To utilize this library for test automation and API testing, you can employ the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: ... try { JsonAssert.IsValid(schema, json); } catch(Exception e) { Console.Error.WriteLine(e); } ... The following presents the printed stack trace for the preceding example. It's important to note that when utilizing JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch Expected (Schema Line: 6:31): data type #integer Actual (Json Line: 3:14): found #string inferred by \"not number\" at RelogicLabs.JsonSchema.Tree.RuntimeContext.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JNode.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JDataType.MatchForReport(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.<>c__DisplayClass22_0.b__1(JDataType d) at RelogicLabs.JsonSchema.Utilities.CollectionExtension.ForEach[T](IEnumerable`1 enumeration, Action`1 action) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 For more information about the schema syntax format and library functionalities, please refer to the reference documentation here." + "keywords": "Getting Started This guide will walk you through the essential steps to quickly get up and running with New JSON Schema library. It is also assumes a modest familiarity with the .NET SDK and .NET CLI (command-line interface) toolchain including basic familiarity with NuGet packages. Additionally, it considers a certain level of knowledge in C# language. NuGet Library Package To get started, launch your preferred IDE (such as Visual Studio, JetBrains Rider, or VS Code) and open the C# project where you intend to include this library package. Within your IDE, navigate to the NuGet package manager and search for the package by the name 'RelogicLabs.JsonSchema'. Subsequently, proceed to add or install the package to your project. Alternatively, you can use the .NET CLI to add the package to your project. Simply run the following command, replacing 1.x.x with either the latest version or your preferred version: dotnet add package RelogicLabs.JsonSchema --version 1.x.x To verify the successful integration of the library into your project, you may manually inspect your project file, typically named .csproj, using a text editor, and search for the following XML snippet within the file: For additional information regarding this library package, you can visit the NuGet package repository page of this library here. Write a Sample to Test With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema. using RelogicLabs.JsonSchema; namespace CSharpApplication; public class SampleSchema { public bool CheckIsValid() { var schema = \"\"\" %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } \"\"\"; var json = \"\"\" { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } \"\"\"; JsonSchema jsonSchema = new(schema); return jsonSchema.IsValid(json); } } Create Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors. { \"user\": { \"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the WriteError method to display the errors if validation fails is as follows: ... JsonSchema jsonSchema = new(schema); if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by \"not number\". Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of \"not number\" Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern \"[a-z_]{3,30}\" is expected but found \"john doe\" that mismatches with pattern. Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, \"profile\"...ing, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}} is expected but found {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": \"Doe\", \"a...: \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {\"user\": {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, ...ng, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}}} is expected but found {\"user\": {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": ... \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}}. Assertion for Validation To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: ... try { JsonAssert.IsValid(schema, json); } catch(Exception e) { Console.Error.WriteLine(e); } ... The following presents the printed stack trace for the preceding example. It's important to note that when using JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch Expected (Schema Line: 6:31): data type #integer Actual (Json Line: 3:14): found #string inferred by \"not number\" at RelogicLabs.JsonSchema.Tree.RuntimeContext.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JNode.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JDataType.MatchForReport(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.<>c__DisplayClass22_0.b__1(JDataType d) at RelogicLabs.JsonSchema.Utilities.CollectionExtension.ForEach[T](IEnumerable`1 enumeration, Action`1 action) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 For more information about the schema syntax format and library functionalities, please refer to the reference documentation here." }, "articles/sourcebuild.html": { "href": "articles/sourcebuild.html", "title": "Build from Source Code | Json Schema", - "keywords": "pre code { font-size: 1.1em; } Build from Source Code This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. Within this document, we will navigate through these steps, presenting them clearly and straightforwardly. Build the Library To get started, clone the project from the following URL using your preferred Git client (command line or GUI). You can open a terminal and enter the following Git clone command as shown below: git clone https://github.com/relogiclabs/JsonSchema-DotNet.git Next, use .NET build command dotnet build to build the project and Retrieve the DLL file, RelogicLabs.JsonSchema.dll from the bin folder. Add the Library to Your Project To integrate the library with your project, you can create a libs folder within your project directory and place the retrieved DLL file into the designated folder. Alternatively, if your IDE supports adding references, you can conveniently select the DLL from the libs folder. Alternatively, you can manually modify your project file .csproj using a text editor and include the following XML snippet: libs\\RelogicLabs.JsonSchema.dll Additionally, this project has a dependency on ANTLR runtime, which you can integrate by executing the following command: dotnet add package Antlr4.Runtime.Standard --version 4.13.1 Write a Sample to Test With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema. using RelogicLabs.JsonSchema; namespace CSharpApplication; public class SampleSchema { public bool CheckIsValid() { var schema = \"\"\" %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } \"\"\"; var json = \"\"\" { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } \"\"\"; JsonSchema jsonSchema = new(schema); return jsonSchema.IsValid(json); } } For more information about the schema syntax format and library functionalities, please refer to the reference documentation here. Create Some Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors. { \"user\": { \"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the WriteError method to display the errors if validation fails is as follows: ... JsonSchema jsonSchema = new(schema); if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by \"not number\". Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of \"not number\" Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern \"[a-z_]{3,30}\" is expected but found \"john doe\" that mismatches with pattern. Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, \"profile\"...ing, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}} is expected but found {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": \"Doe\", \"a...: \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {\"user\": {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, ...ng, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}}} is expected but found {\"user\": {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": ... \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}}." + "keywords": "Build from Source Code This comprehensive guide illustrates the procedures for retrieving source code from a GitHub repository, compiling the project source code into a library, and seamlessly integrating the compiled library into your project. Within this document, we will navigate through these steps, presenting them clearly and straightforwardly. Build the Library To get started, clone the project from the following URL using your preferred Git client (command line or GUI). You can open a terminal and enter the following Git clone command as shown below: git clone https://github.com/relogiclabs/JsonSchema-DotNet.git Next, use .NET build command dotnet build to build the project and Retrieve the DLL file, RelogicLabs.JsonSchema.dll from the bin folder. Add the Library to Your Project To integrate the library with your project, you can create a libs folder within your project directory and place the retrieved DLL file into the designated folder. Alternatively, if your IDE supports adding references, you can conveniently select the DLL from the libs folder. Alternatively, you can manually modify your project file .csproj using a text editor and include the following XML snippet: libs\\RelogicLabs.JsonSchema.dll Additionally, this project has a dependency on ANTLR runtime, which you can integrate by executing the following command: dotnet add package Antlr4.Runtime.Standard --version 4.13.1 Write a Sample to Test With the necessary components in place, you are now prepared to create a sample schema and validate a corresponding JSON against the schema. The subsequent example presents a C# class featuring a method designed for validating a sample JSON based on a provided schema. using RelogicLabs.JsonSchema; namespace CSharpApplication; public class SampleSchema { public bool CheckIsValid() { var schema = \"\"\" %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } \"\"\"; var json = \"\"\" { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } \"\"\"; JsonSchema jsonSchema = new(schema); return jsonSchema.IsValid(json); } } Create Validation Errors Let's intentionally introduce a few errors by modifying the previous JSON document and then examine the validation results. To begin, we'll alter the id within the user object to a string type and observe the outcome. Additionally, we'll modify the username by inserting a space into its value, thus creating an invalid username. Below is the revised JSON representation, now containing these purposeful errors. { \"user\": { \"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } To achieve the desired outcome, please make the following changes to the preceding code. Specifically, ensure that any schema validation errors are displayed in the console. The modified code snippet that invokes the WriteError method to display the errors if validation fails is as follows: ... JsonSchema jsonSchema = new(schema); if(!jsonSchema.IsValid(json)) jsonSchema.WriteError(); ... Here is the error as displayed in the console. More specific errors will be listed first, followed by more general errors. Consequently, the specific errors will precisely pinpoint the issues within the JSON document, while the generic errors will provide contextual information about where the errors occurred. Schema (Line: 6:31) Json (Line: 3:14) [DTYP04]: Data type mismatch. Data type #integer is expected but found #string inferred by \"not number\". Schema (Line: 6:14) [FUNC03]: Function @range(1, 10000) is applicable on #number but applied on #string of \"not number\" Schema (Line: 8:20) Json (Line: 4:20) [REGX01]: Regex pattern does not match. String of pattern \"[a-z_]{3,30}\" is expected but found \"john doe\" that mismatches with pattern. Schema (Line: 5:12) Json (Line: 2:12) [VALD01]: Validation Failed. Value {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, \"profile\"...ing, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}} is expected but found {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": \"Doe\", \"a...: \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}. Schema (Line: 4:0) Json (Line: 1:0) [VALD01]: Validation Failed. Value {\"user\": {\"id\": @range(1, 10000) #integer, \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": \"user\" #string, \"isActive\": #boolean, ...ng, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string} #object #null}}} is expected but found {\"user\": {\"id\": \"not number\", \"username\": \"john doe\", \"role\": \"user\", \"isActive\": true, \"profile\": {\"firstName\": \"John\", \"lastName\": ... \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\"}}}}. Assertion for Validation To utilize this library for test automation and API testing, you can use the following alternative code snippet to perform assertions on input JSON against a specified schema. For instance, let's examine how to assert the JSON, which has been intentionally altered to introduce some errors, against the aforementioned schema. The following demonstrates the adjusted code for asserting the JSON with errors: ... try { JsonAssert.IsValid(schema, json); } catch(Exception e) { Console.Error.WriteLine(e); } ... The following presents the printed stack trace for the preceding example. It's important to note that when using JsonAssert, it throws an exception upon encountering the first error, thus preventing the continuation of processing the rest of the schema: RelogicLabs.JsonSchema.Exceptions.JsonSchemaException: DTYP04: Data type mismatch Expected (Schema Line: 6:31): data type #integer Actual (Json Line: 3:14): found #string inferred by \"not number\" at RelogicLabs.JsonSchema.Tree.RuntimeContext.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JNode.FailWith(Exception exception) at RelogicLabs.JsonSchema.Types.JDataType.MatchForReport(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.<>c__DisplayClass22_0.b__1(JDataType d) at RelogicLabs.JsonSchema.Utilities.CollectionExtension.ForEach[T](IEnumerable`1 enumeration, Action`1 action) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JObject.Match(JNode node) at RelogicLabs.JsonSchema.Types.JValidator.Match(JNode node) at RelogicLabs.JsonSchema.Types.JRoot.Match(JNode node) at RelogicLabs.JsonSchema.JsonAssert.IsValid(String schemaExpected, String jsonActual) at CSharpApplication.SampleSchema.CheckIsValid() in /SampleSchema.cs:line 61 For more information about the schema syntax format and library functionalities, please refer to the reference documentation here." }, "articles/specification.html": { "href": "articles/specification.html", @@ -437,6 +437,6 @@ "index.html": { "href": "index.html", "title": "A New JSON Schema | Json Schema", - "keywords": "pre code { font-size: 1.1em; } A New JSON Schema A JSON Schema is crucial for making communication, interoperability, validation, testing, documentation, and specification seamless. All of this combined contributes to better maintenance and evolution of data-driven applications and systems. For a comprehensive overview of the roles and uses of JSON Schema in modern web applications, we invite you to explore our dedicated post available here. Design Goals The traditional standard JSON Schema rigorously follows the conventional JSON structure, which unfortunately comes at the expense of simplicity, conciseness, and readability. Our goal is to develop a new JSON Schema that promotes these essential aspects that were previously missing. This new schema is simple, lucid, easy to grasp, and doesn't require much prior knowledge to understand it. It also offers a shallow learning curve for both reading and writing. Additionally, its simplicity and conciseness allow us and machines to read-write more efficiently. Moreover, a large set of constraint data types and functions within the core schema promotes the precise definition of JSON documents, significantly reducing the potential for communication gaps among collaborators. Furthermore, its inherent extensibility not only facilitates the test automation process in API testing but also simplifies the integrations of new constraints and functionalities to meet the diverse requirements of modern web services. Basic Example Let's explore an example of our schema for a typical JSON API response containing information about a user profile or account. The schema is very self-explanatory and thus almost no prior knowledge is required to understand the schema and the JSON responses specified by this schema. %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"registeredAt\": #time, \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"dateOfBirth\": #date, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } In the above example, two types of constraint or rule descriptors are used: constraint functions (also known as validation functions, such as @range(1, 10000)) and constraint data types (also known as validation data types, such as #integer). All constraint functions begin with the @ symbol, while all constraint data types start with #. C-style comments are also permitted in the schema. Please note that address can be null (eg. an optional input for users) and if it is null then no constraints of address are applicable. The following JSON is one of the examples which can successfully validate against the above schema. To start your journey with the JSON validation library, please consult the documentation available here. { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"registeredAt\": \"2023-09-06T15:10:30.639Z\", \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"dateOfBirth\": \"1993-06-17\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } Extended Example The next example represents an expanded version of the previous one, which brings more complexity. To effectively construct such schemas with multiple layers of nested structures, it's beneficial to have a fundamental understanding of this schema format. While the syntax may seem difficult at first, it becomes straightforward once you have a basic understanding of it. For more detailed information, reference documentation is available here. %title: \"Extended User Profile Dashboard API Response\" %version: 2.0.0 %include: RelogicLabs.JsonSchema.Tests.Positive.ExternalFunctions, RelogicLabs.JsonSchema.Tests %pragma IgnoreUndefinedProperties: true %define $post: { \"id\": @range(1, 1000) #integer, \"title\": @length(10, 100) #string, \"content\": @length(30, 1000) #string, \"tags\": $tags } #object %define $product: { \"id\": @length(2, 10) @regex(\"[a-z][a-z0-9]+\") #string, \"name\": @length(5, 30) #string, \"brand\": @length(5, 30) #string, \"price\": @range(0.1, 1000000), \"inStock\": #boolean, \"specs\": { \"cpu\": @length(5, 30) #string, \"ram\": @regex(\"[0-9]{1,2}GB\") #string, \"storage\": @regex(\"[0-9]{1,4}GB (SSD|HDD)\") #string } #object #null } %define $tags: @length(1, 10) #array($tag) %define $tag: @length(3, 20) @regex(\"[A-Za-z_]+\") #string %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"registeredAt\": #time, \"profile\": { \"firstName\": @regex(\"[A-Za-z]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z]{3,50}\") #string, \"dateOfBirth\": @date(\"DD-MM-YYYY\") #string, \"age\": @range(18, 128) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null, \"hobbies\": !? }, \"posts\": @length(0, 1000) #object*($post) #array, \"preferences\": { \"theme\": @enum(\"light\", \"dark\") #string, \"fontSize\": @range(9, 24) #integer, \"autoSave\": #boolean } }, \"products\": #object*($product) #array, \"weather\": { \"temperature\": @range(-50.0, 60.0) #float, \"isCloudy\": #boolean } } The subsequent JSON sample is an illustrative example that successfully validates against the expanded schema mentioned earlier. Within this example, recurring JSON structure appear that can be validated through defining components. By reusing defined components, you can achieve a clear and concise schema when validating large JSON with repetitive structures instead of duplicating large and complex validation constraints across the schema. This improves the overall readability and maintainability of the schema. { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"registeredAt\": \"2023-09-06T15:10:30.639Z\", \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"dateOfBirth\": \"17-06-1993\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } }, \"posts\": [ { \"id\": 1, \"title\": \"Introduction to JSON\", \"content\": \"JSON (JavaScript Object Notation) is a lightweight data interchange format...\", \"tags\": [ \"JSON\", \"tutorial\", \"data\" ] }, { \"id\": 2, \"title\": \"Working with JSON in C#\", \"content\": \"C# provides built-in support for working with JSON...\", \"tags\": [ \"CSharp\", \"JSON\", \"tutorial\" ] }, { \"id\": 3, \"title\": \"Introduction to JSON Schema\", \"content\": \"A JSON schema defines the structure and data types of JSON objects...\", \"tags\": [ \"Schema\", \"JSON\", \"tutorial\" ] } ], \"preferences\": { \"theme\": \"dark\", \"fontSize\": 14, \"autoSave\": true } }, \"products\": [ { \"id\": \"p1\", \"name\": \"Smartphone\", \"brand\": \"TechGiant\", \"price\": 599.99, \"inStock\": true, \"specs\": null }, { \"id\": \"p2\", \"name\": \"Laptop\", \"brand\": \"SuperTech\", \"price\": 1299.99, \"inStock\": false, \"specs\": { \"cpu\": \"Intel i7\", \"ram\": \"16GB\", \"storage\": \"512GB SSD\" } } ], \"weather\": { \"temperature\": 25.5, \"isCloudy\": true, \"conditions\": null } } For more information about the schema syntax format and library functionalities, please refer to the reference documentation here." + "keywords": "pre code { font-size: 1.1em; } A New JSON Schema A JSON Schema is crucial for making communication, interoperability, validation, testing, documentation, and specification seamless. All of this combined contributes to better maintenance and evolution of data-driven applications and systems. For a comprehensive overview of the roles and uses of JSON Schema in modern web applications, we invite you to explore our dedicated post available here. Design Goals The traditional standard JSON Schema rigorously follows the conventional JSON structure, which unfortunately comes at the expense of simplicity, conciseness, and readability. Our goal is to develop a new JSON Schema that promotes these essential aspects that were previously missing. This new schema is simple, lucid, easy to grasp, and doesn't require much prior knowledge to understand it. It also offers a shallow learning curve for both reading and writing. Additionally, its simplicity and conciseness allow us and machines to read-write more efficiently. Moreover, a large set of constraint data types and functions within the core schema promotes the precise definition of JSON documents, significantly reducing the potential for communication gaps among collaborators. Furthermore, its inherent extensibility not only facilitates the test automation process in API testing but also simplifies the integrations of new constraints and functionalities to meet the diverse requirements of modern web services. Basic Example Let's explore an example of our schema for a typical JSON API response containing information about a user profile or account. The schema is very self-explanatory and thus almost no prior knowledge is required to understand the schema and the JSON responses specified by this schema. %title: \"User Profile Response\" %version: 1.0.0 %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, /*currently only one role is allowed by system*/ \"role\": \"user\" #string, \"isActive\": #boolean, //user account current status \"registeredAt\": #time, \"profile\": { \"firstName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z ]{3,50}\") #string, \"dateOfBirth\": #date, \"age\": @range(18, 130) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null } } } In the above example, two types of constraint or rule descriptors are used: constraint functions (also known as validation functions, such as @range(1, 10000)) and constraint data types (also known as validation data types, such as #integer). All constraint functions begin with the @ symbol, while all constraint data types start with #. C-style comments are also permitted in the schema. Please note that address can be null (eg. an optional input for users) and if it is null then no constraints of address are applicable. The following JSON is one of the examples which can successfully validate against the above schema. To start your journey with the JSON validation library, please consult the documentation available here. { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"user\", \"isActive\": true, \"registeredAt\": \"2023-09-06T15:10:30.639Z\", \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"dateOfBirth\": \"1993-06-17\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } } } } Extended Example The next example represents an expanded version of the previous one, which brings more complexity. To effectively construct such schemas with multiple layers of nested structures, it's beneficial to have a fundamental understanding of this schema format. While the syntax may seem difficult at first, it becomes straightforward once you have a basic understanding of it. For more detailed information, reference documentation is available here. %title: \"Extended User Profile Dashboard API Response\" %version: 2.0.0 %include: RelogicLabs.JsonSchema.Tests.Positive.ExternalFunctions, RelogicLabs.JsonSchema.Tests %pragma IgnoreUndefinedProperties: true %define $post: { \"id\": @range(1, 1000) #integer, \"title\": @length(10, 100) #string, \"content\": @length(30, 1000) #string, \"tags\": $tags } #object %define $product: { \"id\": @length(2, 10) @regex(\"[a-z][a-z0-9]+\") #string, \"name\": @length(5, 30) #string, \"brand\": @length(5, 30) #string, \"price\": @range(0.1, 1000000), \"inStock\": #boolean, \"specs\": { \"cpu\": @length(5, 30) #string, \"ram\": @regex(\"[0-9]{1,2}GB\") #string, \"storage\": @regex(\"[0-9]{1,4}GB (SSD|HDD)\") #string } #object #null } %define $tags: @length(1, 10) #string*($tag) #array %define $tag: @length(3, 20) @regex(\"[A-Za-z_]+\") #string %schema: { \"user\": { \"id\": @range(1, 10000) #integer, /*username does not allow special characters*/ \"username\": @regex(\"[a-z_]{3,30}\") #string, \"role\": @enum(\"user\", \"admin\") #string, \"isActive\": #boolean, //user account current status \"registeredAt\": @time(\"DD-MM-YYYY hh:mm:ss\") #string, \"profile\": { \"firstName\": @regex(\"[A-Za-z]{3,50}\") #string, \"lastName\": @regex(\"[A-Za-z]{3,50}\") #string, \"dateOfBirth\": @date(\"DD-MM-YYYY\") #string, \"age\": @range(18, 128) #integer, \"email\": @email #string, \"pictureURL\": @url #string, \"address\": { \"street\": @length(10, 200) #string, \"city\": @length(3, 50) #string, \"country\": @regex(\"[A-Za-z ]{3,50}\") #string } #object #null, \"hobbies\": !? }, \"posts\": @length(0, 1000) #object*($post) #array, \"preferences\": { \"theme\": @enum(\"light\", \"dark\") #string, \"fontSize\": @range(9, 24) #integer, \"autoSave\": #boolean } }, \"products\": #object*($product) #array, \"weather\": { \"temperature\": @range(-50.0, 60.0) #float, \"isCloudy\": #boolean } } The subsequent JSON sample is an illustrative example that successfully validates against the expanded schema mentioned earlier. Within this example, recurring JSON structure appear that can be validated through defining components. By reusing defined components, you can achieve a clear and concise schema when validating large JSON with repetitive structures instead of duplicating large and complex validation constraints across the schema. This improves the overall readability and maintainability of the schema. { \"user\": { \"id\": 1234, \"username\": \"johndoe\", \"role\": \"admin\", \"isActive\": true, \"registeredAt\": \"06-09-2023 15:10:30\", \"profile\": { \"firstName\": \"John\", \"lastName\": \"Doe\", \"dateOfBirth\": \"17-06-1993\", \"age\": 30, \"email\": \"john.doe@example.com\", \"pictureURL\": \"https://example.com/picture.jpg\", \"address\": { \"street\": \"123 Some St\", \"city\": \"Some town\", \"country\": \"Some Country\" } }, \"posts\": [ { \"id\": 1, \"title\": \"Introduction to JSON\", \"content\": \"JSON (JavaScript Object Notation) is a lightweight data interchange format...\", \"tags\": [ \"JSON\", \"tutorial\", \"data\" ] }, { \"id\": 2, \"title\": \"Working with JSON in C#\", \"content\": \"C# provides built-in support for working with JSON...\", \"tags\": [ \"CSharp\", \"JSON\", \"tutorial\" ] }, { \"id\": 3, \"title\": \"Introduction to JSON Schema\", \"content\": \"A JSON schema defines the structure and data types of JSON objects...\", \"tags\": [ \"Schema\", \"JSON\", \"tutorial\" ] } ], \"preferences\": { \"theme\": \"dark\", \"fontSize\": 14, \"autoSave\": true } }, \"products\": [ { \"id\": \"p1\", \"name\": \"Smartphone\", \"brand\": \"TechGiant\", \"price\": 599.99, \"inStock\": true, \"specs\": null }, { \"id\": \"p2\", \"name\": \"Laptop\", \"brand\": \"SuperTech\", \"price\": 1299.99, \"inStock\": false, \"specs\": { \"cpu\": \"Intel i11\", \"ram\": \"11GB\", \"storage\": \"11GB SSD\" } } ], \"weather\": { \"temperature\": 25.5, \"isCloudy\": true, \"conditions\": null } } For more information about the schema syntax format and library functionalities, please refer to the reference documentation here." } } \ No newline at end of file diff --git a/JsonSchema/docs/index.md b/JsonSchema/docs/index.md index 04ca5c2..0bec31f 100644 --- a/JsonSchema/docs/index.md +++ b/JsonSchema/docs/index.md @@ -72,7 +72,7 @@ The next example represents an expanded version of the previous one, which bring %title: "Extended User Profile Dashboard API Response" %version: 2.0.0 %include: RelogicLabs.JsonSchema.Tests.Positive.ExternalFunctions, - RelogicLabs.JsonSchema.Tests + RelogicLabs.JsonSchema.Tests %pragma IgnoreUndefinedProperties: true @@ -96,7 +96,7 @@ The next example represents an expanded version of the previous one, which bring } #object #null } -%define $tags: @length(1, 10) #array($tag) +%define $tags: @length(1, 10) #string*($tag) #array %define $tag: @length(3, 20) @regex("[A-Za-z_]+") #string %schema: @@ -105,10 +105,9 @@ The next example represents an expanded version of the previous one, which bring "id": @range(1, 10000) #integer, /*username does not allow special characters*/ "username": @regex("[a-z_]{3,30}") #string, - /*currently only one role is allowed by system*/ - "role": "user" #string, + "role": @enum("user", "admin") #string, "isActive": #boolean, //user account current status - "registeredAt": #time, + "registeredAt": @time("DD-MM-YYYY hh:mm:ss") #string, "profile": { "firstName": @regex("[A-Za-z]{3,50}") #string, "lastName": @regex("[A-Za-z]{3,50}") #string, @@ -143,9 +142,9 @@ The subsequent JSON sample is an illustrative example that successfully validate "user": { "id": 1234, "username": "johndoe", - "role": "user", + "role": "admin", "isActive": true, - "registeredAt": "2023-09-06T15:10:30.639Z", + "registeredAt": "06-09-2023 15:10:30", "profile": { "firstName": "John", "lastName": "Doe", @@ -213,9 +212,9 @@ The subsequent JSON sample is an illustrative example that successfully validate "price": 1299.99, "inStock": false, "specs": { - "cpu": "Intel i7", - "ram": "16GB", - "storage": "512GB SSD" + "cpu": "Intel i11", + "ram": "11GB", + "storage": "11GB SSD" } } ], @@ -226,4 +225,4 @@ The subsequent JSON sample is an illustrative example that successfully validate } } ``` -For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). +For more information about the schema syntax format and library functionalities, please refer to the reference documentation [here](/JsonSchema-DotNet/api/index.html). \ No newline at end of file