<PackageReference Include="NJsonSchema" Version="11.3.2" />

JsonReferenceResolver

public class 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.IO; using System.Linq; using System.Net; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; namespace NJsonSchema { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] 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 : Path.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; } private static string UnescapeReferenceSegment(string segment) { string text = WebUtility.UrlDecode(segment); return text.Replace("~1", "/").Replace("~0", "~"); } public virtual IJsonReference ResolveDocumentReference(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver) { List<string> list = jsonPath.Split(new char[1] { '/' }).Skip(1).ToList(); for (int i = 0; i < list.Count; i++) { list[i] = UnescapeReferenceSegment(list[i]); } IJsonReference jsonReference = ResolveDocumentReference(rootObject, list, targetType, contractResolver, new HashSet<object>()); if (jsonReference == null) throw new InvalidOperationException("Could not resolve the path '" + jsonPath + "'."); return jsonReference; } [AsyncStateMachine(typeof(<ResolveFileReferenceAsync>d__9))] public virtual Task<IJsonReference> ResolveFileReferenceAsync(string filePath, CancellationToken cancellationToken = default(CancellationToken)) { <ResolveFileReferenceAsync>d__9 stateMachine = default(<ResolveFileReferenceAsync>d__9); 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__10))] public virtual Task<IJsonReference> ResolveUrlReferenceAsync(string url, CancellationToken cancellationToken = default(CancellationToken)) { <ResolveUrlReferenceAsync>d__10 stateMachine = default(<ResolveUrlReferenceAsync>d__10); 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__11))] private Task<IJsonReference> ResolveReferenceAsync(object rootObject, string jsonPath, Type targetType, IContractResolver contractResolver, bool append, CancellationToken cancellationToken = default(CancellationToken)) { <ResolveReferenceAsync>d__11 stateMachine = default(<ResolveReferenceAsync>d__11); 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 Path.Combine(Path.GetDirectoryName(documentPath), array[0]); } [AsyncStateMachine(typeof(<ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__13))] private Task<IJsonReference> ResolveFileReferenceWithAlreadyResolvedCheckAsync(string filePath, Type targetType, IContractResolver contractResolver, string jsonPath, bool append, CancellationToken cancellationToken) { <ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__13 stateMachine = default(<ResolveFileReferenceWithAlreadyResolvedCheckAsync>d__13); 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.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__14))] private Task<IJsonReference> ResolveUrlReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath, Type targetType, IContractResolver contractResolver, bool append, CancellationToken cancellationToken) { <ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__14 stateMachine = default(<ResolveUrlReferenceWithAlreadyResolvedCheckAsync>d__14); 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; } [return: System.Runtime.CompilerServices.Nullable(2)] 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); } [return: System.Runtime.CompilerServices.Nullable(2)] 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 JsonConvert.DeserializeObject(value, targetType, settings) as IJsonReference; } return obj as IJsonReference; } 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 && (jsonExtensionObject.ExtensionData?.ContainsKey(text)).GetValueOrDefault()) return ResolveDocumentReference(jsonExtensionObject.ExtensionData[text], segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects); foreach (ContextualAccessorInfo item in from p in ContextualTypeExtensions.GetContextualAccessors(obj.GetType()) where !AttributeExtensions.IsAttributeDefined<JsonIgnoreAttribute>(p, true) select p) { string name = item.GetName(); if (name == text) { object value2 = item.GetValue(obj); if (value2 != null) return ResolveDocumentReference(value2, segments.Skip(1).ToList(), targetType, contractResolver, checkedObjects); } } } return null; } } }