Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating JsonSchema.Net #6

Merged
merged 5 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/dotnet-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
with:
dotnet-version: |
6.0.x
8.0.x
- name: Install dependencies
run: dotnet restore
- name: Build
Expand All @@ -42,6 +43,9 @@ jobs:
needs: build
if: (success() || failure()) && github.event_name == 'pull_request'
name: Publish Unit Test Results
permissions:
checks: write
pull-requests: write
steps:
- name: Download Artifacts
uses: actions/download-artifact@v2
Expand Down
6 changes: 0 additions & 6 deletions Graeae.Models.Tests/DevTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,5 @@ public class DevTest
[Test]
public void Test()
{
var array = new[] { 0, 1, 2, 3, 4, 5, 6 };

var span = array.AsSpan();
var subSpan = span[7..];

Console.WriteLine(JsonSerializer.Serialize(subSpan.ToArray()));
}
}
7 changes: 5 additions & 2 deletions Graeae.Models.Tests/DocumentBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Graeae.Models.Tests;
// code is simple.
public class DocumentBuilderTests
{
[Test]
public void BuildDocument()
{
var doc = new OpenApiDocument("3.1.0", new("title", "1.0")
Expand All @@ -19,7 +20,7 @@ public void BuildDocument()
Email = "[email protected]",
Name = "me you",
Url = new Uri("https://you.com"),
ExtensionData = new() { ["key"] = new JsonArray { 1, 2, 3 } }
ExtensionData = new() { ["key"] = new JsonArray(1, 2, 3) }
},
Description = "this is an api",
License = new("generic license")
Expand Down Expand Up @@ -134,8 +135,10 @@ public void BuildDocument()
}
}
};
Console.WriteLine(YamlSerializer.Serialize(doc, TestEnvironment.TestOutputSerializerOptions));
}

[Test]
public void PetStoreExample()
{
var document = new OpenApiDocument("3.0.0",
Expand Down Expand Up @@ -299,6 +302,6 @@ public void PetStoreExample()
}
};

Console.WriteLine(YamlSerializer.Serialize(document));
Console.WriteLine(YamlSerializer.Serialize(document, TestEnvironment.TestOutputSerializerOptions));
}
}
4 changes: 3 additions & 1 deletion Graeae.Models.Tests/Graeae.Models.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<nowarn>NUnit2005</nowarn>
<JsonSerializerIsReflectionEnabledByDefault Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Graeae.Models.Tests/RefResolutionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void ResolvePathItem()
var file = "api-with-examples.yaml";
var fullFileName = GetFile(file);

var document = YamlSerializer.Deserialize<OpenApiDocument>(File.ReadAllText(fullFileName));
var document = YamlSerializer.Deserialize<OpenApiDocument>(File.ReadAllText(fullFileName), TestEnvironment.SerializerOptions);

var pathItem = document!.Find<PathItem>(JsonPointer.Parse("/paths/~1v2"));

Expand All @@ -28,7 +28,7 @@ public void ResolveExample()
var file = "api-with-examples.yaml";
var fullFileName = GetFile(file);

var document = YamlSerializer.Deserialize<OpenApiDocument>(File.ReadAllText(fullFileName));
var document = YamlSerializer.Deserialize<OpenApiDocument>(File.ReadAllText(fullFileName), TestEnvironment.SerializerOptions);

var example = document!.Find<Example>(JsonPointer.Parse("/paths/~1v2/get/responses/203/content/application~1json/examples/foo"));

Expand Down
28 changes: 19 additions & 9 deletions Graeae.Models.Tests/SpecificationExamples.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections;
using System.Text.Encodings.Web;
using System.Text.Json;
using Json.More;
Expand Down Expand Up @@ -25,15 +26,21 @@ public void RoundTripYaml(string fileName)

try
{
var document = YamlSerializer.Deserialize<OpenApiDocument>(yaml);
var document = YamlSerializer.Deserialize<OpenApiDocument>(yaml, TestEnvironment.SerializerOptions);

var returnToYaml = YamlSerializer.Serialize(document);
var returnToYaml = YamlSerializer.Serialize(document, TestEnvironment.SerializerOptions);

Console.WriteLine(returnToYaml);
}
catch (Exception e)
{
Console.WriteLine($"{JsonSerializer.Serialize(e.Data)}");
var data = new Dictionary<string, object?>();
foreach (DictionaryEntry entry in e.Data)
{
data[entry.Key.ToString()!] = entry.Value;
}

Console.WriteLine($"{JsonSerializer.Serialize(data, TestEnvironment.TestOutputSerializerOptions)}");
throw;
}
}
Expand Down Expand Up @@ -61,19 +68,22 @@ public void RoundTripJson(string fileName)
var yaml = yamlStream.Documents.First();
var json = yaml.ToJsonNode();
Console.WriteLine(json);
var document = json.Deserialize<OpenApiDocument>();
var document = json.Deserialize<OpenApiDocument>(TestEnvironment.SerializerOptions);

var returnToJson = JsonSerializer.SerializeToNode(document, new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
})!;
var returnToJson = JsonSerializer.SerializeToNode(document, TestEnvironment.TestOutputSerializerOptions)!;

Console.WriteLine(returnToJson);
Assert.That(() => json.IsEquivalentTo(returnToJson));
}
catch (Exception e)
{
Console.WriteLine($"{JsonSerializer.Serialize(e.Data)}");
var data = new Dictionary<string, object?>();
foreach (DictionaryEntry entry in e.Data)
{
data[entry.Key.ToString()!] = entry.Value;
}

Console.WriteLine($"{JsonSerializer.Serialize(data, TestEnvironment.TestOutputSerializerOptions)}");
throw;
}
}
Expand Down
43 changes: 42 additions & 1 deletion Graeae.Models.Tests/TestEnvironment.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
using Graeae.Models.SchemaDraft4;
using Json.Schema;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace Graeae.Models.Tests;

[SetUpFixture]
public class TestEnvironment
{
public static readonly JsonSerializerOptions SerializerOptions =
new()
{
TypeInfoResolverChain = { TestSerializerContext.Default },
};

public static readonly JsonSerializerOptions TestOutputSerializerOptions =
new()
{
TypeInfoResolverChain = { TestSerializerContext.Default },
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};

[OneTimeSetUp]
public void Setup()
{
Draft4Support.Enable();
}
}
}

[JsonSerializable(typeof(OpenApiDocument))]
[JsonSerializable(typeof(Draft4ExclusiveMaximumKeyword))]
[JsonSerializable(typeof(Draft4ExclusiveMinimumKeyword))]
[JsonSerializable(typeof(Draft4IdKeyword))]
[JsonSerializable(typeof(Draft4TypeKeyword))]
[JsonSerializable(typeof(NullableKeyword))]
[JsonSerializable(typeof(ParameterStyle))]
[JsonSerializable(typeof(ParameterStyle?))]
[JsonSerializable(typeof(ParameterLocation))]
[JsonSerializable(typeof(ParameterLocation?))]
[JsonSerializable(typeof(SecuritySchemeLocation))]
[JsonSerializable(typeof(SecuritySchemeLocation?))]

[JsonSerializable(typeof(JsonSchema))]
[JsonSerializable(typeof(EvaluationResults))]

[JsonSerializable(typeof(JsonNode))]
[JsonSerializable(typeof(JsonObject))]
[JsonSerializable(typeof(Dictionary<string, object>))]
[JsonSerializable(typeof(Dictionary<string, JsonSchema>))]
internal partial class TestSerializerContext : JsonSerializerContext;
17 changes: 4 additions & 13 deletions Graeae.Models.Tests/ValidationTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Text.Encodings.Web;
using System.Text.Json;
using Json.Schema;
using Yaml2JsonNode;
Expand All @@ -21,19 +20,15 @@ public void ValidateOpenApiDoc_3_0(string fileName)
var yaml = File.ReadAllText(fullFileName);
var instance = YamlSerializer.Parse(yaml).First().ToJsonNode();
var schemaFileName = GetFile("openapi-schema-3.0.json");
var schema = JsonSchema.FromFile(schemaFileName);
var schema = JsonSchema.FromFile(schemaFileName, TestEnvironment.SerializerOptions);

var results = schema.Evaluate(instance, new EvaluationOptions
{
OutputFormat = OutputFormat.List,
EvaluateAs = SchemaDraft4.Draft4Support.Draft4Version
});

Console.WriteLine(JsonSerializer.Serialize(results, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
Console.WriteLine(JsonSerializer.Serialize(results, TestEnvironment.TestOutputSerializerOptions));

Assert.IsTrue(results.IsValid);
}
Expand All @@ -47,18 +42,14 @@ public void ValidateOpenApiDoc_3_1(string fileName)
var yaml = File.ReadAllText(fullFileName);
var instance = YamlSerializer.Parse(yaml).First().ToJsonNode();
var schemaFileName = GetFile("openapi-schema-3.1.json");
var schema = JsonSchema.FromFile(schemaFileName);
var schema = JsonSchema.FromFile(schemaFileName, TestEnvironment.SerializerOptions);

var results = schema.Evaluate(instance, new EvaluationOptions
{
OutputFormat = OutputFormat.List
});

Console.WriteLine(JsonSerializer.Serialize(results, new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}));
Console.WriteLine(JsonSerializer.Serialize(results, TestEnvironment.TestOutputSerializerOptions));

Assert.IsTrue(results.IsValid);
}
Expand Down
16 changes: 8 additions & 8 deletions Graeae.Models/Callback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class Callback : Dictionary<CallbackKeyExpression, PathItem>, IRefTargetC
/// </summary>
public ExtensionData? ExtensionData { get; set; }

internal static Callback FromNode(JsonNode? node)
internal static Callback FromNode(JsonNode? node, JsonSerializerOptions? options)
{
if (node is not JsonObject obj)
throw new JsonException("Expected an object");
Expand All @@ -35,19 +35,19 @@ internal static Callback FromNode(JsonNode? node)
else
{
callback = new Callback();
callback.Import(obj);
callback.Import(obj, options);
}
return callback;
}

private protected void Import(JsonObject obj)
private protected void Import(JsonObject obj, JsonSerializerOptions? options)
{
ExtensionData = ExtensionData.FromNode(obj);

foreach (var (key, value) in obj)
{
if (key.StartsWith("x-")) continue;
Add(CallbackKeyExpression.Parse(key), PathItem.FromNode(value));
Add(CallbackKeyExpression.Parse(key), PathItem.FromNode(value, options));
}
}

Expand Down Expand Up @@ -75,7 +75,7 @@ private protected void Import(JsonObject obj)
return obj;
}

object? IRefTargetContainer.Resolve(Span<string> keys)
object? IRefTargetContainer.Resolve(ReadOnlySpan<string> keys)
{
if (keys.Length == 0) return null;

Expand Down Expand Up @@ -145,13 +145,13 @@ public CallbackRef(string reference)
Ref = new Uri(reference ?? throw new ArgumentNullException(nameof(reference)), UriKind.RelativeOrAbsolute);
}

async Task IComponentRef.Resolve(OpenApiDocument root)
async Task IComponentRef.Resolve(OpenApiDocument root, JsonSerializerOptions? options)
{
bool import(JsonNode? node)
{
if (node is not JsonObject obj) return false;

Import(obj);
Import(obj, options);
return true;
}

Expand All @@ -175,7 +175,7 @@ public override Callback Read(ref Utf8JsonReader reader, Type typeToConvert, Jso
var obj = JsonSerializer.Deserialize<JsonObject>(ref reader, options) ??
throw new JsonException("Expected an object");

return Callback.FromNode(obj);
return Callback.FromNode(obj, options);
}

public override void Write(Utf8JsonWriter writer, Callback value, JsonSerializerOptions options)
Expand Down
24 changes: 12 additions & 12 deletions Graeae.Models/ComponentCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,23 @@ public class ComponentCollection : IRefTargetContainer
/// </summary>
public ExtensionData? ExtensionData { get; set; }

internal static ComponentCollection FromNode(JsonNode? node)
internal static ComponentCollection FromNode(JsonNode? node, JsonSerializerOptions? options)
{
if (node is not JsonObject obj)
throw new JsonException("Expected an object");

var components = new ComponentCollection
{
Schemas = obj.MaybeDeserialize<Dictionary<string, JsonSchema>>("schemas"),
Responses = obj.MaybeMap("responses", Response.FromNode),
Parameters = obj.MaybeMap("parameters", Parameter.FromNode),
Schemas = obj.MaybeDeserialize<Dictionary<string, JsonSchema>>("schemas", options),
Responses = obj.MaybeMap("responses", x => Response.FromNode(x, options)),
Parameters = obj.MaybeMap("parameters", x => Parameter.FromNode(x, options)),
Examples = obj.MaybeMap("examples", Example.FromNode),
RequestBodies = obj.MaybeMap("requestBodies", RequestBody.FromNode),
Headers = obj.MaybeMap("headers", Header.FromNode),
SecuritySchemes = obj.MaybeMap("securitySchemes", SecurityScheme.FromNode),
RequestBodies = obj.MaybeMap("requestBodies", x => RequestBody.FromNode(x, options)),
Headers = obj.MaybeMap("headers", x => Header.FromNode(x, options)),
SecuritySchemes = obj.MaybeMap("securitySchemes", x => SecurityScheme.FromNode(x, options)),
Links = obj.MaybeMap("links", Link.FromNode),
Callbacks = obj.MaybeMap("callbacks", Callback.FromNode),
PathItems = obj.MaybeMap("pathItems", PathItem.FromNode),
Callbacks = obj.MaybeMap("callbacks", x => Callback.FromNode(x, options)),
PathItems = obj.MaybeMap("pathItems", x => PathItem.FromNode(x, options)),
ExtensionData = ExtensionData.FromNode(obj)
};

Expand All @@ -107,7 +107,7 @@ internal static ComponentCollection FromNode(JsonNode? node)
obj.MaybeAddMap("examples", components.Examples, Example.ToNode);
obj.MaybeAddMap("requestBodies", components.RequestBodies, x => RequestBody.ToNode(x, options));
obj.MaybeAddMap("headers", components.Headers, x => Header.ToNode(x, options));
obj.MaybeAddMap("securitySchemes", components.SecuritySchemes, SecurityScheme.ToNode);
obj.MaybeAddMap("securitySchemes", components.SecuritySchemes, x => SecurityScheme.ToNode(x, options));
obj.MaybeAddMap("links", components.Links, Link.ToNode);
obj.MaybeAddMap("callbacks", components.Callbacks, x => Callback.ToNode(x, options));
obj.MaybeAddMap("pathItems", components.PathItems, x => PathItem.ToNode(x, options));
Expand All @@ -116,7 +116,7 @@ internal static ComponentCollection FromNode(JsonNode? node)
return obj;
}

object? IRefTargetContainer.Resolve(Span<string> keys)
object? IRefTargetContainer.Resolve(ReadOnlySpan<string> keys)
{
if (keys.Length == 0) return this;

Expand Down Expand Up @@ -206,7 +206,7 @@ public override ComponentCollection Read(ref Utf8JsonReader reader, Type typeToC
var obj = JsonSerializer.Deserialize<JsonObject>(ref reader, options) ??
throw new JsonException("Expected an object");

return ComponentCollection.FromNode(obj);
return ComponentCollection.FromNode(obj, options);
}

public override void Write(Utf8JsonWriter writer, ComponentCollection value, JsonSerializerOptions options)
Expand Down
Loading
Loading