Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/RSuter/NJsonSchema
Browse files Browse the repository at this point in the history
  • Loading branch information
RicoSuter committed Jul 11, 2018
2 parents c8ff510 + a5721f9 commit 5f8cf1e
Show file tree
Hide file tree
Showing 12 changed files with 259 additions and 25 deletions.
1 change: 1 addition & 0 deletions build/04_RunTests.bat
Expand Up @@ -2,3 +2,4 @@ dotnet test "%~dp0/../src\NJsonSchema.Tests\NJsonSchema.Tests.csproj" -c Release
dotnet test "%~dp0/../src\NJsonSchema.CodeGeneration.Tests\NJsonSchema.CodeGeneration.Tests.csproj" -c Release
dotnet test "%~dp0/../src\NJsonSchema.CodeGeneration.CSharp.Tests\NJsonSchema.CodeGeneration.CSharp.Tests.csproj" -c Release
dotnet test "%~dp0/../src\NJsonSchema.CodeGeneration.TypeScript.Tests\NJsonSchema.CodeGeneration.TypeScript.Tests.csproj" -c Release
dotnet test "%~dp0/../src\NJsonSchema.Yaml.Tests\NJsonSchema.Yaml.Tests.csproj" -c Release
45 changes: 45 additions & 0 deletions src/NJsonSchema.Yaml.Tests/NJsonSchema.Yaml.Tests.csproj
@@ -0,0 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net46;net45</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup>
<DocumentationFile>bin\Debug\$(TargetFramework)\NJsonSchema.Yaml.Tests.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
<PackageReference Condition="'$(TargetFramework)' == 'netcoreapp2.0'" Include="System.ComponentModel.Annotations" Version="4.4.0" />
<Reference Condition="'$(TargetFramework)' == 'net45'" Include="System.ComponentModel.DataAnnotations">
</Reference>
<Reference Condition="'$(TargetFramework)' == 'net46'" Include="System.ComponentModel.DataAnnotations">
</Reference>
<PackageReference Include="NodaTime" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NJsonSchema\NJsonSchema.csproj" />
<ProjectReference Include="..\NJsonSchema.Yaml\NJsonSchema.Yaml.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="References\YamlReferencesTest\collection.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="References\YamlReferencesTest\collection.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="References\YamlReferencesTest\json_schema_with_yaml_reference.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="References\YamlReferencesTest\json_schema_with_json_reference.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="References\YamlReferencesTest\yaml_schema_with_json_reference.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="References\YamlReferencesTest\yaml_schema_with_yaml_reference.yaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
@@ -0,0 +1,8 @@
{
"myInt": {
"type": "integer"
},
"myBool": {
"type": "boolean"
}
}
@@ -0,0 +1,5 @@
---
myInt:
type: integer
myBool:
type: boolean
@@ -0,0 +1,16 @@
{
"type": "object",
"properties": {
"bar": {
"$ref": "./collection.json#/myBool"
},
"foo": {
"$ref": "#/definitions/collection/myInt"
}
},
"definitions": {
"collection": {
"$ref": "./collection.json"
}
}
}
@@ -0,0 +1,16 @@
{
"type": "object",
"properties": {
"bar": {
"$ref": "./collection.yaml#/myBool"
},
"foo": {
"$ref": "#/definitions/collection/myInt"
}
},
"definitions": {
"collection": {
"$ref": "./collection.yaml"
}
}
}
@@ -0,0 +1,10 @@
---
type: object
properties:
bar:
"$ref": "./collection.json#/myBool"
foo:
"$ref": "#/definitions/collection/myInt"
definitions:
collection:
"$ref": "./collection.json"
@@ -0,0 +1,10 @@
---
type: object
properties:
bar:
"$ref": "./collection.yaml#/myBool"
foo:
"$ref": "#/definitions/collection/myInt"
definitions:
collection:
"$ref": "./collection.yaml"
38 changes: 38 additions & 0 deletions src/NJsonSchema.Yaml.Tests/References/YamlReferencesTests.cs
@@ -0,0 +1,38 @@
using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Xunit;

namespace NJsonSchema.Yaml.Tests.References
{
public class LocalReferencesTests
{
[Theory]
[InlineData("/References/YamlReferencesTest/json_schema_with_json_reference.json", "./collection.json")]
[InlineData("/References/YamlReferencesTest/yaml_schema_with_json_reference.yaml", "./collection.json")]
[InlineData("/References/YamlReferencesTest/yaml_schema_with_yaml_reference.yaml", "./collection.yaml")]
[InlineData("/References/YamlReferencesTest/json_schema_with_yaml_reference.json", "./collection.yaml")]
public async Task When_yaml_schema_has_references_it_works(string relativePath, string documentPath)
{
//// Arrange
var path = GetTestDirectory() + relativePath;

//// Act
var schema = await JsonSchemaYaml.FromFileAsync(path);
var json = schema.ToJson();

//// Assert
Assert.Equal(JsonObjectType.Integer, schema.Properties["foo"].ActualTypeSchema.Type);
Assert.Equal(1, schema.Definitions.Count);
Assert.Equal(documentPath, schema.Definitions["collection"].DocumentPath);
}

private string GetTestDirectory()
{
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
return Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
}
}
}
86 changes: 77 additions & 9 deletions src/NJsonSchema.Yaml/JsonSchemaYaml.cs
Expand Up @@ -6,34 +6,54 @@
// <author>Rico Suter, mail@rsuter.com</author>
//-----------------------------------------------------------------------

using System;
using System.Dynamic;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Generation;
using NJsonSchema.Infrastructure;
using NJsonSchema.References;
using YamlDotNet.Serialization;

namespace NJsonSchema.Yaml
{
/// <summary>Extension methods to load and save <see cref="JsonSchema4"/> from/to YAML.</summary>
public static class JsonSchemaYaml
{
/// <summary>Creates a JSON Schema from a YAML string.</summary>
/// <param name="data">The JSON data.</param>
/// <summary>Deserializes a JSON string to a <see cref="JsonSchema4" />.</summary>
/// <param name="data">The JSON string.</param>
/// <returns>The JSON Schema.</returns>
public static async Task<JsonSchema4> FromYamlAsync(string data)
{
return await JsonSchemaYaml.FromYamlAsync(data, null, CreateReferenceResolverFactory()).ConfigureAwait(false);
}

/// <summary>Deserializes a JSON string to a <see cref="JsonSchema4" />.</summary>
/// <param name="data">The JSON string.</param>
/// <param name="documentPath">The document path (URL or file path) for resolving relative document references.</param>
/// <returns>The <see cref="JsonSchema4"/>.</returns>
public static async Task<JsonSchema4> FromYamlAsync(string data, string documentPath = null)
/// <returns>The JSON Schema.</returns>
public static async Task<JsonSchema4> FromYamlAsync(string data, string documentPath)
{
return await JsonSchemaYaml.FromYamlAsync(data, documentPath, CreateReferenceResolverFactory()).ConfigureAwait(false);
}

/// <summary>Deserializes a JSON string to a <see cref="JsonSchema4" />.</summary>
/// <param name="data">The JSON string.</param>
/// <param name="documentPath">The document path (URL or file path) for resolving relative document references.</param>
/// <param name="referenceResolverFactory">The JSON reference resolver factory.</param>
/// <returns>The JSON Schema.</returns>
public static async Task<JsonSchema4> FromYamlAsync(string data, string documentPath, Func<JsonSchema4, JsonReferenceResolver> referenceResolverFactory)
{
var deserializer = new DeserializerBuilder().Build();
var yamlObject = deserializer.Deserialize(new StringReader(data));

var serializer = new SerializerBuilder()
.JsonCompatible()
.Build();

var json = serializer.Serialize(yamlObject);
return await JsonSchema4.FromJsonAsync(json, documentPath).ConfigureAwait(false);
return await JsonSchema4.FromJsonAsync(json, documentPath, referenceResolverFactory).ConfigureAwait(false);
}

/// <summary>Converts the JSON Schema to YAML.</summary>
Expand All @@ -52,18 +72,66 @@ public static string ToYaml(this JsonSchema4 document)
/// <param name="filePath">The file path.</param>
/// <returns>The <see cref="JsonSchema4" />.</returns>
public static async Task<JsonSchema4> FromFileAsync(string filePath)
{
return await FromFileAsync(filePath, CreateReferenceResolverFactory()).ConfigureAwait(false);
}

/// <summary>Creates a JSON Schema from a JSON file.</summary>
/// <param name="filePath">The file path.</param>
/// <param name="referenceResolverFactory">The JSON reference resolver factory.</param>
/// <returns>The <see cref="JsonSchema4" />.</returns>
public static async Task<JsonSchema4> FromFileAsync(string filePath, Func<JsonSchema4, JsonReferenceResolver> referenceResolverFactory)
{
var data = await DynamicApis.FileReadAllTextAsync(filePath).ConfigureAwait(false);
return await FromYamlAsync(data, filePath).ConfigureAwait(false);
return await FromYamlAsync(data, filePath, referenceResolverFactory).ConfigureAwait(false);
}

/// <summary>Creates a JSON Schema from an URL.</summary>
/// <param name="url">The URL.</param>
/// <param name="referenceResolverFactory">The JSON reference resolver factory.</param>
/// <returns>The <see cref="JsonSchema4"/>.</returns>
public static async Task<JsonSchema4> FromUrlAsync(string url)
public static async Task<JsonSchema4> FromUrlAsync(string url, Func<JsonSchema4, JsonReferenceResolver> referenceResolverFactory)
{
var data = await DynamicApis.HttpGetAsync(url).ConfigureAwait(false);
return await FromYamlAsync(data, url).ConfigureAwait(false);
return await FromYamlAsync(data, url, referenceResolverFactory).ConfigureAwait(false);
}

private static string ConvertYamlToJson(string data)
{
var deserializer = new DeserializerBuilder().Build();
var yamlObject = deserializer.Deserialize(new StringReader(data));

var serializer = new SerializerBuilder()
.JsonCompatible()
.Build();

var json = serializer.Serialize(yamlObject);
return json;
}

private static Func<JsonSchema4, JsonReferenceResolver> CreateReferenceResolverFactory()
{
JsonReferenceResolver ReferenceResolverFactory(JsonSchema4 schema) =>
new JsonAndYamlReferenceResolver(new JsonSchemaResolver(schema, new JsonSchemaGeneratorSettings()));
return ReferenceResolverFactory;
}

private class JsonAndYamlReferenceResolver : JsonReferenceResolver
{
public JsonAndYamlReferenceResolver(JsonSchemaResolver schemaResolver)
: base(schemaResolver)
{
}

public override async Task<IJsonReference> ResolveFileReferenceAsync(string filePath)
{
return await FromFileAsync(filePath, schema => this).ConfigureAwait(false);
}

public override async Task<IJsonReference> ResolveUrlReferenceAsync(string url)
{
return await FromUrlAsync(url, schema => this).ConfigureAwait(false);
}
}
}
}
25 changes: 22 additions & 3 deletions src/NJsonSchema.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2024
VisualStudioVersion = 15.0.26403.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema", "NJsonSchema\NJsonSchema.csproj", "{7B7A2E32-E808-4A19-98B1-37E766580F8C}"
EndProject
Expand All @@ -25,9 +25,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema.CodeGeneration.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema.Yaml", "NJsonSchema.Yaml\NJsonSchema.Yaml.csproj", "{9EAB6FAB-10AC-4AB2-BA5B-103CE6A17E88}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NJsonSchema.Demo.Performance", "NJsonSchema.Demo.Performance\NJsonSchema.Demo.Performance.csproj", "{75B834E0-1F0D-4BC2-911D-5CF079BCE73B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema.Demo.Performance", "NJsonSchema.Demo.Performance\NJsonSchema.Demo.Performance.csproj", "{75B834E0-1F0D-4BC2-911D-5CF079BCE73B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NJsonSchema.Benchmark", "NJsonSchema.Benchmark\NJsonSchema.Benchmark.csproj", "{E59CE32B-181F-4AAE-BF62-772AEEFC3177}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema.Benchmark", "NJsonSchema.Benchmark\NJsonSchema.Benchmark.csproj", "{E59CE32B-181F-4AAE-BF62-772AEEFC3177}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NJsonSchema.Yaml.Tests", "NJsonSchema.Yaml.Tests\NJsonSchema.Yaml.Tests.csproj", "{990EF464-C967-4E08-8C3D-0568A47B6D2A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -209,6 +211,22 @@ Global
{E59CE32B-181F-4AAE-BF62-772AEEFC3177}.Release|x64.Build.0 = Release|Any CPU
{E59CE32B-181F-4AAE-BF62-772AEEFC3177}.Release|x86.ActiveCfg = Release|Any CPU
{E59CE32B-181F-4AAE-BF62-772AEEFC3177}.Release|x86.Build.0 = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|ARM.ActiveCfg = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|ARM.Build.0 = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|x64.ActiveCfg = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|x64.Build.0 = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|x86.ActiveCfg = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Debug|x86.Build.0 = Debug|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|Any CPU.Build.0 = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|ARM.ActiveCfg = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|ARM.Build.0 = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|x64.ActiveCfg = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|x64.Build.0 = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|x86.ActiveCfg = Release|Any CPU
{990EF464-C967-4E08-8C3D-0568A47B6D2A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -221,6 +239,7 @@ Global
{E767A007-6007-4898-B80A-FE4ACBF2C588} = {785552E3-F3BB-4AEB-B5CF-819AE38AEA8F}
{75B834E0-1F0D-4BC2-911D-5CF079BCE73B} = {785552E3-F3BB-4AEB-B5CF-819AE38AEA8F}
{E59CE32B-181F-4AAE-BF62-772AEEFC3177} = {785552E3-F3BB-4AEB-B5CF-819AE38AEA8F}
{990EF464-C967-4E08-8C3D-0568A47B6D2A} = {785552E3-F3BB-4AEB-B5CF-819AE38AEA8F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9D5EDC80-5611-493B-804B-8B364816952B}
Expand Down

0 comments on commit 5f8cf1e

Please sign in to comment.