JsonSchemaReferenceUtilities
Provides utilities to resolve and set JSON schema references.
using Newtonsoft.Json.Serialization;
using NJsonSchema.References;
using NJsonSchema.Visitors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace NJsonSchema
{
public static class JsonSchemaReferenceUtilities
{
private class JsonReferenceUpdater : AsyncJsonReferenceVisitorBase
{
private readonly object _rootObject;
private readonly JsonReferenceResolver _referenceResolver;
private readonly IContractResolver _contractResolver;
private bool _replaceRefsRound;
public JsonReferenceUpdater(object rootObject, JsonReferenceResolver referenceResolver, IContractResolver contractResolver)
: base(contractResolver)
{
_rootObject = rootObject;
_referenceResolver = referenceResolver;
_contractResolver = contractResolver;
}
[AsyncStateMachine(typeof(<VisitAsync>d__5))]
public override Task VisitAsync(object obj, CancellationToken cancellationToken = default(CancellationToken))
{
<VisitAsync>d__5 stateMachine = default(<VisitAsync>d__5);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.obj = obj;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<VisitJsonReferenceAsync>d__6))]
protected override Task<IJsonReference> VisitJsonReferenceAsync(IJsonReference reference, string path, string typeNameHint, CancellationToken cancellationToken)
{
<VisitJsonReferenceAsync>d__6 stateMachine = default(<VisitJsonReferenceAsync>d__6);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.reference = reference;
stateMachine.path = path;
stateMachine.typeNameHint = typeNameHint;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
}
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;
}
protected override IJsonReference VisitJsonReference(IJsonReference reference, string path, string typeNameHint)
{
if (reference.Reference != null) {
if (!_removeExternalReferences || reference.Reference.DocumentPath == null)
_schemaReferences[reference] = reference.Reference.ActualObject;
else {
IJsonReference reference2 = reference.Reference;
object rootObject = reference2.FindParentDocument();
reference.ReferencePath = reference2.DocumentPath + JsonPathUtilities.GetJsonPath(rootObject, reference2, _contractResolver).TrimEnd(new char[1] {
'#'
});
}
} else if (_removeExternalReferences && _rootObject != reference && reference.DocumentPath != null) {
throw new NotSupportedException("removeExternalReferences not supported");
}
return reference;
}
}
public static Task UpdateSchemaReferencesAsync(object rootObject, JsonReferenceResolver referenceResolver)
{
return UpdateSchemaReferencesAsync(rootObject, referenceResolver, new DefaultContractResolver(), default(CancellationToken));
}
[AsyncStateMachine(typeof(<UpdateSchemaReferencesAsync>d__1))]
public static Task UpdateSchemaReferencesAsync(object rootObject, JsonReferenceResolver referenceResolver, IContractResolver contractResolver, CancellationToken cancellationToken = default(CancellationToken))
{
<UpdateSchemaReferencesAsync>d__1 stateMachine = default(<UpdateSchemaReferencesAsync>d__1);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.rootObject = rootObject;
stateMachine.referenceResolver = referenceResolver;
stateMachine.contractResolver = contractResolver;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
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).Visit(rootObject);
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];
}
}
}
}