JsonReferenceResolver
Resolves JSON Pointer references.
using Namotion.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NJsonSchema.Infrastructure;
using NJsonSchema.References;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace NJsonSchema
{
public class JsonReferenceResolver
{
private readonly JsonSchemaAppender _schemaAppender;
private readonly Dictionary<string, IJsonReference> _resolvedObjects = new Dictionary<string, IJsonReference>();
public JsonReferenceResolver(JsonSchemaAppender schemaAppender)
{
_schemaAppender = schemaAppender;
}
public static Func<JsonSchema, JsonReferenceResolver> CreateJsonReferenceResolverFactory(ITypeNameGenerator typeNameGenerator)
{
return (JsonSchema schema) => new JsonReferenceResolver(new JsonSchemaAppender(schema, typeNameGenerator));
}
public void AddDocumentReference(string documentPath, IJsonReference schema)
{
_resolvedObjects[documentPath.Contains("://") ? documentPath : DynamicApis.GetFullPath(documentPath)] = schema;
}
[AsyncStateMachine(typeof(<ResolveReferenceAsync>d__5))]
public Task<IJsonReference> ResolveReferenceAsync(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver, CancellationToken cancellationToken = default(CancellationToken))
{
<ResolveReferenceAsync>d__5 stateMachine = default(<ResolveReferenceAsync>d__5);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.rootObject = rootObject;
stateMachine.jsonPath = jsonPath;
stateMachine.targetType = targetType;
stateMachine.contractResolver = contractResolver;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ResolveReferenceWithoutAppendAsync>d__6))]
public Task<IJsonReference> ResolveReferenceWithoutAppendAsync(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver, CancellationToken cancellationToken = default(CancellationToken))
{
<ResolveReferenceWithoutAppendAsync>d__6 stateMachine = default(<ResolveReferenceWithoutAppendAsync>d__6);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.rootObject = rootObject;
stateMachine.jsonPath = jsonPath;
stateMachine.targetType = targetType;
stateMachine.contractResolver = contractResolver;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public virtual IJsonReference ResolveDocumentReference(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver)
{
List<string> segments = jsonPath.Split(new char[1] {
'/'
}).Skip(1).ToList();
IJsonReference jsonReference = ResolveDocumentReference(rootObject, segments, targetType, contractResolver, new HashSet<object>());
if (jsonReference == null)
throw new InvalidOperationException("Could not resolve the path '" + jsonPath + "'.");
return jsonReference;
}
[AsyncStateMachine(typeof(<ResolveFileReferenceAsync>d__8))]
public virtual Task<IJsonReference> ResolveFileReferenceAsync(string filePath, CancellationToken cancellationToken = default(CancellationToken))
{
<ResolveFileReferenceAsync>d__8 stateMachine = default(<ResolveFileReferenceAsync>d__8);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.filePath = filePath;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ResolveUrlReferenceAsync>d__9))]
public virtual Task<IJsonReference> ResolveUrlReferenceAsync(string url, CancellationToken cancellationToken = default(CancellationToken))
{
<ResolveUrlReferenceAsync>d__9 stateMachine = default(<ResolveUrlReferenceAsync>d__9);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.url = url;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ResolveReferenceAsync>d__10))]
private Task<IJsonReference> ResolveReferenceAsync(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver, bool append, CancellationToken cancellationToken = default(CancellationToken))
{
<ResolveReferenceAsync>d__10 stateMachine = default(<ResolveReferenceAsync>d__10);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.rootObject = rootObject;
stateMachine.jsonPath = jsonPath;
stateMachine.targetType = targetType;
stateMachine.contractResolver = contractResolver;
stateMachine.append = append;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
public virtual string ResolveFilePath(string documentPath, string jsonPath)
{
string[] array = Regex.Split(jsonPath, "(?=#)");
return DynamicApis.PathCombine(DynamicApis.PathGetDirectoryName(documentPath), array[0]);
}
[AsyncStateMachine(typeof(<ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__12))]
private Task<IJsonReference> ResolveFileReferenceWithAlreadyResolvedCheckAsync(string filePath, Type targetType, IContractResolver contractResolver, string jsonPath, bool append, CancellationToken cancellationToken)
{
<ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__12 stateMachine = default(<ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__12);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.filePath = filePath;
stateMachine.targetType = targetType;
stateMachine.contractResolver = contractResolver;
stateMachine.jsonPath = jsonPath;
stateMachine.append = append;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__13))]
private Task<IJsonReference> ResolveUrlReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath, Type targetType, IContractResolver contractResolver, bool append, CancellationToken cancellationToken)
{
<ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__13 stateMachine = default(<ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__13);
stateMachine.<>t__builder = AsyncTaskMethodBuilder<IJsonReference>.Create();
stateMachine.<>4__this = this;
stateMachine.fullJsonPath = fullJsonPath;
stateMachine.jsonPath = jsonPath;
stateMachine.targetType = targetType;
stateMachine.contractResolver = contractResolver;
stateMachine.append = append;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
private IJsonReference ResolveDocumentReference(object obj, List<string> segments, Type targetType, IContractResolver contractResolver, HashSet<object> checkedObjects)
{
if (obj == null || obj is string || checkedObjects.Contains(obj))
return null;
IJsonReference jsonReference = obj as IJsonReference;
if (jsonReference != null && jsonReference.Reference != null) {
IJsonReference jsonReference2 = ResolveDocumentReferenceWithoutDereferencing(jsonReference.Reference, segments, targetType, contractResolver, checkedObjects);
if (jsonReference2 == null)
return ResolveDocumentReferenceWithoutDereferencing(obj, segments, targetType, contractResolver, checkedObjects);
return jsonReference2;
}
return ResolveDocumentReferenceWithoutDereferencing(obj, segments, targetType, contractResolver, checkedObjects);
}
private IJsonReference ResolveDocumentReferenceWithoutDereferencing(object obj, List<string> segments, Type targetType, IContractResolver contractResolver, HashSet<object> checkedObjects)
{
if (segments.Count == 0) {
if (obj is IDictionary) {
JsonSerializerSettings settings = new JsonSerializerSettings {
ContractResolver = contractResolver
};
string value = JsonConvert.SerializeObject(obj, settings);
return (IJsonReference)JsonConvert.DeserializeObject(value, targetType, settings);
}
return (IJsonReference)obj;
}
checkedObjects.Add(obj);
string text = segments[0];
IDictionary dictionary = obj as IDictionary;
if (dictionary != null) {
if (dictionary.Contains(text))
return ResolveDocumentReference(dictionary[text], segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects);
} else if (obj is IEnumerable) {
if (int.TryParse(text, out int result)) {
object[] array = ((IEnumerable)obj).Cast<object>().ToArray();
if (array.Length > result)
return ResolveDocumentReference(array[result], segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects);
}
} else {
IJsonExtensionObject jsonExtensionObject = obj as IJsonExtensionObject;
if (jsonExtensionObject != null) {
bool? nullable = jsonExtensionObject.ExtensionData?.ContainsKey(text);
bool flag = true;
if ((nullable.GetValueOrDefault() == flag) & nullable.HasValue)
return ResolveDocumentReference(jsonExtensionObject.ExtensionData[text], segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects);
}
foreach (ContextualAccessorInfo item in from p in ContextualTypeExtensions.GetContextualAccessors(obj.GetType())
where p.get_AccessorType().GetInheritedAttribute<JsonIgnoreAttribute>() == null
select p) {
string name = item.GetName();
if (name == text) {
object value2 = item.GetValue(obj);
return ResolveDocumentReference(value2, segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects);
}
}
}
return null;
}
}
}