Skip to content

Commit

Permalink
Merge pull request #52 from gregsdennis/schema-2020-12
Browse files Browse the repository at this point in the history
Schema 2020 12
  • Loading branch information
gregsdennis committed Dec 14, 2020
2 parents 3efbd6b + 4ec4c59 commit 6ff9e0f
Show file tree
Hide file tree
Showing 79 changed files with 1,775 additions and 117 deletions.
54 changes: 30 additions & 24 deletions JsonPointer.Tests/RelativeJsonPointerParseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,32 @@ public static IEnumerable SpecificationExamples
{
get
{
yield return new TestCaseData("1/foo", 1, new[] {"foo"});
yield return new TestCaseData("2/foo/0", 2, new[] {"foo", "0"});
yield return new TestCaseData("3/", 3, new[] {""});
yield return new TestCaseData("4/a~1b", 4, new[] {"a/b"});
yield return new TestCaseData("5/c%d", 5, new[] {"c%d"});
yield return new TestCaseData("6/e^f", 6, new[] {"e^f"});
yield return new TestCaseData("7/g|h", 7, new[] {"g|h"});
yield return new TestCaseData("8/i\\j", 8, new[] {"i\\j"});
yield return new TestCaseData("9/k\"l", 9, new[] {"k\"l"});
yield return new TestCaseData("10/ ", 10, new[] {" "});
yield return new TestCaseData("11/m~0n", 11, new[] {"m~n"});
yield return new TestCaseData("12/c%25d", 12, new[] {"c%25d"});
yield return new TestCaseData("13/e%5Ef", 13, new[] {"e%5Ef"});
yield return new TestCaseData("14/g%7Ch", 14, new[] {"g%7Ch"});
yield return new TestCaseData("15/i%5Cj", 15, new[] {"i%5Cj"});
yield return new TestCaseData("16/k%22l", 16, new[] {"k%22l"});
yield return new TestCaseData("17/%20", 17, new[] {"%20"});
yield return new TestCaseData("0", 0, new string[] { });
yield return new TestCaseData("1/0", 1, new[] {"0"});
yield return new TestCaseData("2/highly/nested/objects", 2, new[] {"highly", "nested", "objects"});
yield return new TestCaseData("0#", 0, new string[] { });
yield return new TestCaseData("1#", 1, new string[] { });
yield return new TestCaseData("1/foo", 1, 0, new[] {"foo"});
yield return new TestCaseData("2/foo/0", 2, 0, new[] {"foo", "0"});
yield return new TestCaseData("3/", 3, 0, new[] {""});
yield return new TestCaseData("4/a~1b", 4, 0, new[] {"a/b"});
yield return new TestCaseData("5/c%d", 5, 0, new[] {"c%d"});
yield return new TestCaseData("6/e^f", 6, 0, new[] {"e^f"});
yield return new TestCaseData("7/g|h", 7, 0, new[] {"g|h"});
yield return new TestCaseData("8/i\\j", 8, 0, new[] {"i\\j"});
yield return new TestCaseData("9/k\"l", 9, 0, new[] {"k\"l"});
yield return new TestCaseData("10/ ", 10, 0, new[] {" "});
yield return new TestCaseData("11/m~0n", 11, 0, new[] {"m~n"});
yield return new TestCaseData("12/c%25d", 12, 0, new[] {"c%25d"});
yield return new TestCaseData("13/e%5Ef", 13, 0, new[] {"e%5Ef"});
yield return new TestCaseData("14/g%7Ch", 14, 0, new[] {"g%7Ch"});
yield return new TestCaseData("15/i%5Cj", 15, 0, new[] {"i%5Cj"});
yield return new TestCaseData("16/k%22l", 16, 0, new[] {"k%22l"});
yield return new TestCaseData("17/%20", 17, 0, new[] {"%20"});
yield return new TestCaseData("0", 0, 0, new string[] { });
yield return new TestCaseData("1/0", 1, 0, new[] {"0"});
yield return new TestCaseData("2/highly/nested/objects", 2, 0, new[] {"highly", "nested", "objects"});
yield return new TestCaseData("0#", 0, 0, new string[] { });
yield return new TestCaseData("1#", 1, 0, new string[] { });
yield return new TestCaseData("1-1#", 1, -1, new string[] { });
yield return new TestCaseData("1+1#", 1, 1, new string[] { });
yield return new TestCaseData("1-1/path", 1, -1, new[] {"path"});
yield return new TestCaseData("1+1/path", 1, 1, new[] {"path"});
}
}
public static IEnumerable FailureCases
Expand All @@ -51,21 +55,23 @@ public static IEnumerable FailureCases
}

[TestCaseSource(nameof(SpecificationExamples))]
public void Parse(string pointerString, int parentSteps, string[] segments)
public void Parse(string pointerString, int parentSteps, int indexManipulation, string[] segments)
{
var pointer = RelativeJsonPointer.Parse(pointerString);

pointer.ParentSteps.Should().Be((uint) parentSteps);
pointer.ArrayIndexManipulator.Should().Be(indexManipulation);
pointer.Pointer.Segments.Length.Should().Be(segments.Length);
pointer.Pointer.Segments.Select(s => s.Value).Should().BeEquivalentTo(segments);
}

[TestCaseSource(nameof(SpecificationExamples))]
public void TryParse(string pointerString, int parentSteps, string[] segments)
public void TryParse(string pointerString, int parentSteps, int indexManipulation, string[] segments)
{
Assert.IsTrue(RelativeJsonPointer.TryParse(pointerString, out var pointer));

pointer.ParentSteps.Should().Be((uint) parentSteps);
pointer.ArrayIndexManipulator.Should().Be(indexManipulation);
pointer.Pointer.Segments.Length.Should().Be(segments.Length);
pointer.Pointer.Segments.Select(s => s.Value).Should().BeEquivalentTo(segments);
}
Expand Down
2 changes: 2 additions & 0 deletions JsonPointer.Tests/RelativeJsonPointerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ public static IEnumerable SpecificationExamples
{
yield return new TestCaseData("0", "\"baz\"");
yield return new TestCaseData("1/0", "\"bar\"");
yield return new TestCaseData("0-1", "\"bar\"");
yield return new TestCaseData("2/highly/nested/objects", "true");
yield return new TestCaseData("0#", "1");
yield return new TestCaseData("0-1#", "0");
yield return new TestCaseData("1#", "\"foo\"");
}
}
Expand Down
22 changes: 22 additions & 0 deletions JsonPointer/JsonPointer.Net.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions JsonPointer/JsonPointer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<RootNamespace>Json.Pointer</RootNamespace>
<Version>1.1.2</Version>
<Version>1.2.0</Version>
<PackageId>JsonPointer.Net</PackageId>
<Authors>Greg Dennis</Authors>
<Product>JsonPointer.Net</Product>
Expand All @@ -18,7 +18,7 @@
<PackageIcon>json-logo-256.png</PackageIcon>
<PackageReleaseNotes>https://gregsdennis.github.io/json-everything/release-notes/json-pointer.html</PackageReleaseNotes>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.1.2.0</FileVersion>
<FileVersion>1.2.0.0</FileVersion>
<DocumentationFile>JsonPointer.Net.xml</DocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Expand Down
82 changes: 73 additions & 9 deletions JsonPointer/RelativeJsonPointer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace Json.Pointer
/// </summary>
public uint ParentSteps { get; }
/// <summary>
/// Gets the number of lateral steps to take. Applicable only for arrays.
/// </summary>
public int ArrayIndexManipulator { get; }
/// <summary>
/// Gets the pointer to follow after taking <see cref="ParentSteps"/> steps upward.
/// </summary>
public JsonPointer Pointer { get; }
Expand All @@ -32,12 +36,28 @@ private RelativeJsonPointer(uint parentSteps)
{
IsIndexQuery = true;
ParentSteps = parentSteps;
ArrayIndexManipulator = 0;
Pointer = JsonPointer.Empty;
}
private RelativeJsonPointer(uint parentSteps, int arrayIndexManipulator)
{
IsIndexQuery = true;
ParentSteps = parentSteps;
ArrayIndexManipulator = arrayIndexManipulator ;
Pointer = JsonPointer.Empty;
}
private RelativeJsonPointer(uint parentSteps, JsonPointer pointer)
{
IsIndexQuery = false;
ParentSteps = parentSteps;
ArrayIndexManipulator = 0;
Pointer = pointer;
}
private RelativeJsonPointer(uint parentSteps, int arrayIndexManipulator, JsonPointer pointer)
{
IsIndexQuery = false;
ParentSteps = parentSteps;
ArrayIndexManipulator = arrayIndexManipulator;
Pointer = pointer;
}

Expand All @@ -49,6 +69,15 @@ private RelativeJsonPointer(uint parentSteps, JsonPointer pointer)
public static RelativeJsonPointer IndexQuery(uint parentSteps) =>
new RelativeJsonPointer(parentSteps);

/// <summary>
/// Creates an index query pointer.
/// </summary>
/// <param name="parentSteps"></param>
/// <param name="arrayIndexManipulator">The index manipulator.</param>
/// <returns>A Relative JSON Pointer.</returns>
public static RelativeJsonPointer IndexQuery(uint parentSteps, int arrayIndexManipulator) =>
new RelativeJsonPointer(parentSteps, arrayIndexManipulator);

/// <summary>
/// Creates a Relative JSON Pointer from a JSON Pointer and a number of parent steps.
/// </summary>
Expand All @@ -58,6 +87,16 @@ private RelativeJsonPointer(uint parentSteps, JsonPointer pointer)
public static RelativeJsonPointer FromPointer(uint parentSteps, JsonPointer pointer) =>
new RelativeJsonPointer(parentSteps, pointer);

/// <summary>
/// Creates a Relative JSON Pointer from a JSON Pointer and a number of parent steps.
/// </summary>
/// <param name="parentSteps">The number of parent steps.</param>
/// <param name="arrayIndexManipulator">The index manipulator.</param>
/// <param name="pointer">The JSON Pointer.</param>
/// <returns>A Relative JSON Pointer.</returns>
public static RelativeJsonPointer FromPointer(uint parentSteps, int arrayIndexManipulator, JsonPointer pointer) =>
new RelativeJsonPointer(parentSteps, arrayIndexManipulator, pointer);

/// <summary>
/// Parses a JSON Pointer segment from a string.
/// </summary>
Expand All @@ -73,22 +112,32 @@ public static RelativeJsonPointer Parse(string source)
var span = source.AsSpan();
int i = 0;
while (i < span.Length && char.IsDigit(span[i])) i++;

if (i == 0) throw new PointerParseException($"`{nameof(source)}` must start with a non-negative integer");

var number = uint.Parse(span.Slice(0, i).ToString());
if (i == span.Length) return new RelativeJsonPointer(number, JsonPointer.Empty);
var parentSteps = uint.Parse(span.Slice(0, i).ToString());
if (i == span.Length) return new RelativeJsonPointer(parentSteps, JsonPointer.Empty);

int indexManipulation = 0;
if (span[i] == '+' || span[i] == '-')
{
var sign = span[i] == '+' ? 1 : -1;
i++;
var start = i;
while (i < span.Length && char.IsDigit(span[i])) i++;
indexManipulation = sign * int.Parse(span.Slice(start, i - start).ToString());
if (i == span.Length) return new RelativeJsonPointer(parentSteps, indexManipulation, JsonPointer.Empty);
}
if (span[i] == '#')
{
if (i+1 < span.Length) throw new PointerParseException($"{nameof(source)} cannot contain data after a `#`");
return new RelativeJsonPointer(number);
return new RelativeJsonPointer(parentSteps, indexManipulation);
}

if (span[i] != '/') throw new PointerParseException($"{nameof(source)} must contain either a `#` or a pointer after the initial number");

var pointer = JsonPointer.Parse(span.Slice(i).ToString());

return new RelativeJsonPointer(number, pointer);
return new RelativeJsonPointer(parentSteps, indexManipulation, pointer);
}

/// <summary>
Expand Down Expand Up @@ -117,20 +166,35 @@ public static bool TryParse(string source, out RelativeJsonPointer relativePoint
return false;
}

var number = uint.Parse(span.Slice(0, i).ToString());
var parentSteps = uint.Parse(span.Slice(0, i).ToString());
if (i == span.Length)
{
relativePointer = new RelativeJsonPointer(number, JsonPointer.Empty);
relativePointer = new RelativeJsonPointer(parentSteps, JsonPointer.Empty);
return true;
}

int indexManipulation = 0;
if (span[i] == '+' || span[i] == '-')
{
var sign = span[i] == '+' ? 1 : -1;
i++;
var start = i;
while (i < span.Length && char.IsDigit(span[i])) i++;
indexManipulation = sign * int.Parse(span.Slice(start, i - start).ToString());
if (i == span.Length)
{
relativePointer = new RelativeJsonPointer(parentSteps, indexManipulation, JsonPointer.Empty);
return true;
}
}
if (span[i] == '#')
{
if (i + 1 < span.Length)
{
relativePointer = default;
return false;
}
relativePointer = new RelativeJsonPointer(number);
relativePointer = new RelativeJsonPointer(parentSteps, indexManipulation);
return true;
}

Expand All @@ -146,7 +210,7 @@ public static bool TryParse(string source, out RelativeJsonPointer relativePoint
return false;
}

relativePointer = new RelativeJsonPointer(number, pointer);
relativePointer = new RelativeJsonPointer(parentSteps, indexManipulation, pointer);
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions JsonSchema.Tests/FormatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public void Ipv4_Pass()

var value = JsonDocument.Parse("\"100.2.54.3\"");

var result = schema.Validate(value.RootElement, new ValidationOptions{ValidateFormat = true});
var result = schema.Validate(value.RootElement, new ValidationOptions{RequireFormatValidation = true});

Assert.True(result.IsValid);
}
Expand All @@ -25,7 +25,7 @@ public void Ipv4_Fail()

var value = JsonDocument.Parse("\"100.2.5444.3\"");

var result = schema.Validate(value.RootElement, new ValidationOptions {ValidateFormat = true});
var result = schema.Validate(value.RootElement, new ValidationOptions {RequireFormatValidation = true});

Assert.False(result.IsValid);
}
Expand Down
2 changes: 1 addition & 1 deletion JsonSchema.Tests/GithubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public void Issue19_Draft4ShouldInvalidateAsUnrecognizedSchema_NoOption()

var result = schema.Validate(instance.RootElement, new ValidationOptions{OutputFormat = OutputFormat.Detailed});

result.AssertValid();
result.AssertInvalid();
}

[Test]
Expand Down
6 changes: 5 additions & 1 deletion JsonSchema.Tests/Suite/Suite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static IEnumerable<TestCaseData> TestCases()
return GetTests("draft6")
.Concat(GetTests("draft7"))
.Concat(GetTests("draft2019-09"));
//.Concat(GetTests("draft2020-12"));
}

private static IEnumerable<TestCaseData> GetTests(string draftFolder)
Expand All @@ -41,8 +42,11 @@ private static IEnumerable<TestCaseData> GetTests(string draftFolder)
options.ValidateAs = Draft.Draft7;
break;
case "draft2019-09":
options.ValidateAs = Draft.Draft201909;
break;
case "draft2020-12":
// will set this when implementing the next draft
//options.ValidateAs = Draft.Draft2019_09;
//options.ValidateAs = Draft.Draft202012;
break;
}

Expand Down
2 changes: 2 additions & 0 deletions JsonSchema/AdditionalPropertiesKeyword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ namespace Json.Schema
[SchemaDraft(Draft.Draft6)]
[SchemaDraft(Draft.Draft7)]
[SchemaDraft(Draft.Draft201909)]
[SchemaDraft(Draft.Draft202012)]
[Vocabulary(Vocabularies.Applicator201909Id)]
[Vocabulary(Vocabularies.Applicator202012Id)]
[JsonConverter(typeof(AdditionalPropertiesKeywordJsonConverter))]
public class AdditionalPropertiesKeyword : IJsonSchemaKeyword, IRefResolvable, ISchemaContainer, IEquatable<AdditionalPropertiesKeyword>
{
Expand Down
2 changes: 2 additions & 0 deletions JsonSchema/AllOfKeyword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ namespace Json.Schema
[SchemaDraft(Draft.Draft6)]
[SchemaDraft(Draft.Draft7)]
[SchemaDraft(Draft.Draft201909)]
[SchemaDraft(Draft.Draft202012)]
[Vocabulary(Vocabularies.Applicator201909Id)]
[Vocabulary(Vocabularies.Applicator202012Id)]
[JsonConverter(typeof(AllOfKeywordJsonConverter))]
public class AllOfKeyword : IJsonSchemaKeyword, IRefResolvable, ISchemaCollector, IEquatable<AllOfKeyword>
{
Expand Down
2 changes: 2 additions & 0 deletions JsonSchema/AnchorKeyword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ namespace Json.Schema
[SchemaKeyword(Name)]
[SchemaPriority(long.MinValue + 2)]
[SchemaDraft(Draft.Draft201909)]
[SchemaDraft(Draft.Draft202012)]
[Vocabulary(Vocabularies.Core201909Id)]
[Vocabulary(Vocabularies.Core202012Id)]
[JsonConverter(typeof(AnchorKeywordJsonConverter))]
public class AnchorKeyword : IJsonSchemaKeyword, IEquatable<AnchorKeyword>
{
Expand Down
2 changes: 2 additions & 0 deletions JsonSchema/AnyOfKeyword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ namespace Json.Schema
[SchemaDraft(Draft.Draft6)]
[SchemaDraft(Draft.Draft7)]
[SchemaDraft(Draft.Draft201909)]
[SchemaDraft(Draft.Draft202012)]
[Vocabulary(Vocabularies.Applicator201909Id)]
[Vocabulary(Vocabularies.Applicator202012Id)]
[JsonConverter(typeof(AnyOfKeywordJsonConverter))]
public class AnyOfKeyword : IJsonSchemaKeyword, IRefResolvable, ISchemaCollector, IEquatable<AnyOfKeyword>
{
Expand Down

0 comments on commit 6ff9e0f

Please sign in to comment.