JsonSchemaReferenceUtilities
Provides utilities to resolve and set JSON schema references.
using Newtonsoft.Json.Serialization;
using NJsonSchema.References;
using NJsonSchema.Visitors;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace NJsonSchema
{
public static class JsonSchemaReferenceUtilities
{
private class JsonReferenceUpdater : JsonReferenceVisitorBase
{
private readonly object _rootObject;
private readonly JsonReferenceResolver _referenceResolver;
private bool _replaceRefsRound;
public JsonReferenceUpdater(object rootObject, JsonReferenceResolver referenceResolver, IContractResolver contractResolver)
: base(contractResolver)
{
_rootObject = rootObject;
_referenceResolver = referenceResolver;
}
public override async Task VisitAsync(object obj)
{
_replaceRefsRound = true;
await base.VisitAsync(obj);
_replaceRefsRound = false;
await base.VisitAsync(obj);
}
protected override async Task<IJsonReference> VisitJsonReferenceAsync(IJsonReference reference, string path, string typeNameHint)
{
if (reference.ReferencePath != null && reference.Reference == null) {
if (_replaceRefsRound) {
if (path.EndsWith("/definitions/" + typeNameHint) || path.EndsWith("/schemas/" + typeNameHint))
return await _referenceResolver.ResolveReferenceWithoutAppendAsync(_rootObject, reference.ReferencePath).ConfigureAwait(false);
} else
reference.Reference = await _referenceResolver.ResolveReferenceAsync(_rootObject, reference.ReferencePath).ConfigureAwait(false);
}
return reference;
}
}
private class JsonReferencePathUpdater : JsonReferenceVisitorBase
{
private readonly object _rootObject;
private readonly Dictionary<IJsonReference, IJsonReference> _schemaReferences;
private readonly bool _removeExternalReferences;
private readonly IContractResolver _contractResolver;
public JsonReferencePathUpdater(object rootObject, Dictionary<IJsonReference, IJsonReference> schemaReferences, bool removeExternalReferences, IContractResolver contractResolver)
: base(contractResolver)
{
_rootObject = rootObject;
_schemaReferences = schemaReferences;
_removeExternalReferences = removeExternalReferences;
_contractResolver = contractResolver;
}
[AsyncStateMachine(typeof(<VisitJsonReferenceAsync>d__5))]
protected override Task<IJsonReference> VisitJsonReferenceAsync(IJsonReference reference, string path, string typeNameHint)
{
<VisitJsonReferenceAsync>d__5 stateMachine = default(<VisitJsonReferenceAsync>d__5);
stateMachine.<>4__this = this;
stateMachine.reference = reference;
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder<IJsonReference> <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
}
public static Task UpdateSchemaReferencesAsync(object rootObject, JsonReferenceResolver referenceResolver)
{
return UpdateSchemaReferencesAsync(rootObject, referenceResolver, new DefaultContractResolver());
}
public static async Task UpdateSchemaReferencesAsync(object rootObject, JsonReferenceResolver referenceResolver, IContractResolver contractResolver)
{
await new JsonReferenceUpdater(rootObject, referenceResolver, contractResolver).VisitAsync(rootObject).ConfigureAwait(false);
}
public static string ConvertJsonReferences(string data)
{
return data.Replace("$ref", "__referencePath");
}
public static string ConvertPropertyReferences(string data)
{
return data.Replace("__referencePath", "$ref");
}
public static void UpdateSchemaReferencePaths(object rootObject)
{
UpdateSchemaReferencePaths(rootObject, false, new DefaultContractResolver());
}
public static void UpdateSchemaReferencePaths(object rootObject, bool removeExternalReferences, IContractResolver contractResolver)
{
Dictionary<IJsonReference, IJsonReference> dictionary = new Dictionary<IJsonReference, IJsonReference>();
new JsonReferencePathUpdater(rootObject, dictionary, removeExternalReferences, contractResolver).VisitAsync(rootObject).GetAwaiter().GetResult();
IEnumerable<IJsonReference> searchedObjects = (from p in dictionary
select p.Value).Distinct();
IReadOnlyDictionary<object, string> jsonPaths = JsonPathUtilities.GetJsonPaths(rootObject, searchedObjects, contractResolver);
foreach (KeyValuePair<IJsonReference, IJsonReference> item in dictionary) {
item.Key.ReferencePath = jsonPaths[item.Value];
}
}
}
}