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

JsonReferenceResolver

public class JsonReferenceResolver
Resolves JSON Pointer references.
using Microsoft.Runtime.CompilerServices; using NJsonSchema.Infrastructure; using NJsonSchema.References; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace NJsonSchema { public class JsonReferenceResolver { private readonly JsonSchemaResolver _schemaResolver; private readonly Dictionary<string, IJsonReference> _resolvedObjects = new Dictionary<string, IJsonReference>(); public JsonReferenceResolver(JsonSchemaResolver schemaResolver) { _schemaResolver = schemaResolver; } public void AddDocumentReference(string documentPath, IJsonReference schema) { _resolvedObjects[documentPath] = schema; } public async Task<IJsonReference> ResolveReferenceAsync(object rootObject, string jsonPath) { TaskAwaiter<IJsonReference> val = AwaitExtensions.GetAwaiter<IJsonReference>(ResolveReferenceAsync(rootObject, jsonPath, true)); if (!val.get_IsCompleted()) { await val; TaskAwaiter<IJsonReference> val2 = default(TaskAwaiter<IJsonReference>); val = val2; } return val.GetResult(); } public async Task<IJsonReference> ResolveReferenceWithoutAppendAsync(object rootObject, string jsonPath) { TaskAwaiter<IJsonReference> val = AwaitExtensions.GetAwaiter<IJsonReference>(ResolveReferenceAsync(rootObject, jsonPath, false)); if (!val.get_IsCompleted()) { await val; TaskAwaiter<IJsonReference> val2 = default(TaskAwaiter<IJsonReference>); val = val2; } return val.GetResult(); } public virtual IJsonReference ResolveDocumentReference(object rootObject, string jsonPath) { List<string> segments = jsonPath.Split(new char[1] { '/' }).Skip(1).ToList(); IJsonReference jsonReference = ResolveDocumentReference(rootObject, segments, new HashSet<object>()); if (jsonReference == null) throw new InvalidOperationException("Could not resolve the path '" + jsonPath + "'."); return jsonReference; } public virtual async Task<IJsonReference> ResolveFileReferenceAsync(string filePath) { ConfiguredTaskAwaiter val = AwaitExtensions.ConfigureAwait<JsonSchema4>(JsonSchema4.FromFileAsync(filePath, (JsonSchema4 schema) => this), false).GetAwaiter(); if (!val.get_IsCompleted()) { await val; ConfiguredTaskAwaiter val2 = default(ConfiguredTaskAwaiter); val = val2; } return (IJsonReference)val.GetResult(); } public virtual async Task<IJsonReference> ResolveUrlReferenceAsync(string url) { ConfiguredTaskAwaiter val = AwaitExtensions.ConfigureAwait<JsonSchema4>(JsonSchema4.FromUrlAsync(url, (JsonSchema4 schema) => this), false).GetAwaiter(); if (!val.get_IsCompleted()) { await val; ConfiguredTaskAwaiter val2 = default(ConfiguredTaskAwaiter); val = val2; } return (IJsonReference)val.GetResult(); } private async Task<IJsonReference> ResolveReferenceAsync(object rootObject, string jsonPath, bool append) { if (jsonPath == "#") { if (rootObject is IJsonReference) return (IJsonReference)rootObject; throw new InvalidOperationException("Could not resolve the JSON path '#' because the root object is not a JsonSchema4."); } if (jsonPath.StartsWith("#/")) return ResolveDocumentReference(rootObject, jsonPath); ConfiguredTaskAwaitable<IJsonReference> val; ConfiguredTaskAwaiter val2; if (jsonPath.StartsWith("http://") || jsonPath.StartsWith("https://")) { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveUrlReferenceWithAlreadyResolvedCheckAsync(jsonPath, jsonPath, append), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter); val2 = val3; } return (IJsonReference)val2.GetResult(); } string documentPath = (rootObject as IDocumentPathProvider)?.DocumentPath; if (documentPath != null) { if (documentPath.StartsWith("http://") || documentPath.StartsWith("https://")) { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveUrlReferenceWithAlreadyResolvedCheckAsync(new Uri(new Uri(documentPath), jsonPath).ToString(), jsonPath, append), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter); val2 = val3; } return (IJsonReference)val2.GetResult(); } val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveFileReferenceWithAlreadyResolvedCheckAsync(DynamicApis.PathCombine(DynamicApis.PathGetDirectoryName(documentPath), jsonPath), jsonPath, append), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter); val2 = val3; } return (IJsonReference)val2.GetResult(); } throw new NotSupportedException("Could not resolve the JSON path '" + jsonPath + "' because no document path is available."); } private async Task<IJsonReference> ResolveFileReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath, bool append) { try { string[] arr = Regex.Split(fullJsonPath, "(?=#)"); string filePath = arr[0]; ConfiguredTaskAwaitable<IJsonReference> val; ConfiguredTaskAwaiter val2; ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter); if (!_resolvedObjects.ContainsKey(filePath)) { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveFileReferenceAsync(filePath), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; val2 = val3; val3 = default(ConfiguredTaskAwaiter); } IJsonReference result = (IJsonReference)val2.GetResult(); result.DocumentPath = jsonPath; if ((result is JsonSchema4) & append) _schemaResolver.AppendSchema((JsonSchema4)result, filePath.Split('/', '\\').Last().Split(new char[1] { '.' }) .First()); _resolvedObjects[filePath] = result; } IJsonReference jsonReference = _resolvedObjects[filePath]; IJsonReference result2; if (arr.Length == 1) result2 = jsonReference; else { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveReferenceAsync(jsonReference, arr[1]), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; val2 = val3; } result2 = (IJsonReference)val2.GetResult(); } return result2; } catch (Exception innerException) { throw new InvalidOperationException("Could not resolve the JSON path '" + jsonPath + "' with the full JSON path '" + fullJsonPath + "'.", innerException); } } private async Task<IJsonReference> ResolveUrlReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath, bool append) { try { string[] arr = fullJsonPath.Split(new char[1] { '#' }); ConfiguredTaskAwaitable<IJsonReference> val; ConfiguredTaskAwaiter val2; ConfiguredTaskAwaiter val3 = default(ConfiguredTaskAwaiter); if (!_resolvedObjects.ContainsKey(arr[0])) { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveUrlReferenceAsync(arr[0]), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; val2 = val3; val3 = default(ConfiguredTaskAwaiter); } IJsonReference result = (IJsonReference)val2.GetResult(); result.DocumentPath = jsonPath; if ((result is JsonSchema4) & append) _schemaResolver.AppendSchema((JsonSchema4)result, null); _resolvedObjects[arr[0]] = result; } IJsonReference jsonReference = _resolvedObjects[arr[0]]; IJsonReference result2; if (arr.Length == 1) result2 = jsonReference; else { val = AwaitExtensions.ConfigureAwait<IJsonReference>(ResolveReferenceAsync(jsonReference, "#" + arr[1]), false); val2 = val.GetAwaiter(); if (!val2.get_IsCompleted()) { await val2; val2 = val3; } result2 = (IJsonReference)val2.GetResult(); } return result2; } catch (Exception innerException) { throw new InvalidOperationException("Could not resolve the JSON path '" + jsonPath + "' with the full JSON path '" + fullJsonPath + "'.", innerException); } } private IJsonReference ResolveDocumentReference(object obj, List<string> segments, HashSet<object> checkedObjects) { if (obj == null || obj is string || checkedObjects.Contains(obj)) return null; IJsonReference jsonReference; if ((jsonReference = (obj as IJsonReference)) != null && jsonReference.Reference != null) obj = jsonReference.Reference; if (segments.Count == 0) return obj as IJsonReference; checkedObjects.Add(obj); string text = segments[0]; if (obj is IDictionary) { if (((IDictionary)obj).Contains(text)) return ResolveDocumentReference(((IDictionary)obj)[text], segments.Skip(1).ToList(), 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(), checkedObjects); } } else { IJsonExtensionObject jsonExtensionObject = obj as IJsonExtensionObject; if (jsonExtensionObject != null && jsonExtensionObject.ExtensionData?.ContainsKey(text) == true) return ResolveDocumentReference(jsonExtensionObject.ExtensionData[text], segments.Skip(1).ToList(), checkedObjects); foreach (ReflectionCache.PropertyOrField item in from p in ReflectionCache.GetPropertiesAndFields(obj.GetType()) where p.CustomAttributes.JsonIgnoreAttribute == null select p) { if (item.GetName() == text) { object value = item.GetValue(obj); return ResolveDocumentReference(value, segments.Skip(1).ToList(), checkedObjects); } } } return null; } } }