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

JsonReferenceResolver

public class JsonReferenceResolver
Resolves JSON Pointer references.
using NJsonSchema.Infrastructure; 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, JsonSchema4> _resolvedSchemas = new Dictionary<string, JsonSchema4>(); public JsonReferenceResolver(JsonSchemaResolver schemaResolver) { _schemaResolver = schemaResolver; } public void AddDocumentReference(string documentPath, JsonSchema4 schema) { _resolvedSchemas[documentPath] = schema; } public async Task<JsonSchema4> ResolveReferenceAsync(object rootObject, string jsonPath) { if (jsonPath == "#") { if (rootObject is JsonSchema4) return (JsonSchema4)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); if (jsonPath.StartsWith("http://") || jsonPath.StartsWith("https://")) return await ResolveUrlReferenceWithAlreadyResolvedCheckAsync(jsonPath, jsonPath).ConfigureAwait(false); string documentPath = (rootObject as IDocumentPathProvider)?.DocumentPath; if (documentPath != null) { if (documentPath.StartsWith("http://") || documentPath.StartsWith("https://")) return await ResolveUrlReferenceWithAlreadyResolvedCheckAsync(new Uri(new Uri(documentPath), jsonPath).ToString(), jsonPath).ConfigureAwait(false); return await ResolveFileReferenceWithAlreadyResolvedCheckAsync(DynamicApis.PathCombine(DynamicApis.PathGetDirectoryName(documentPath), jsonPath), jsonPath).ConfigureAwait(false); } throw new NotSupportedException("Could not resolve the JSON path '" + jsonPath + "' because no document path is available."); } protected virtual JsonSchema4 ResolveDocumentReference(object rootObject, string jsonPath) { List<string> segments = jsonPath.Split(new char[1] { '/' }).Skip(1).ToList(); JsonSchema4 jsonSchema = ResolveDocumentReference(rootObject, segments, new HashSet<object>()); if (jsonSchema == null) throw new InvalidOperationException("Could not resolve the path '" + jsonPath + "'."); return jsonSchema; } protected virtual async Task<JsonSchema4> ResolveFileReferenceAsync(string filePath) { return await JsonSchema4.FromFileAsync(filePath, (JsonSchema4 schema) => this).ConfigureAwait(false); } protected virtual async Task<JsonSchema4> ResolveUrlReferenceAsync(string url) { return await JsonSchema4.FromUrlAsync(url, (JsonSchema4 schema) => this).ConfigureAwait(false); } private async Task<JsonSchema4> ResolveFileReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath) { try { string[] arr = Regex.Split(fullJsonPath, "(?=#)"); if (!_resolvedSchemas.ContainsKey(arr[0])) { JsonSchema4 jsonSchema = await ResolveFileReferenceAsync(arr[0]).ConfigureAwait(false); _schemaResolver.AppendSchema(jsonSchema, null); _resolvedSchemas[arr[0]] = jsonSchema; } JsonSchema4 jsonSchema2 = _resolvedSchemas[arr[0]]; return (arr.Length != 1) ? (await ResolveReferenceAsync(jsonSchema2, arr[1]).ConfigureAwait(false)) : jsonSchema2; } catch (Exception innerException) { throw new InvalidOperationException("Could not resolve the JSON path '" + jsonPath + "' with the full JSON path '" + fullJsonPath + "'.", innerException); } } private async Task<JsonSchema4> ResolveUrlReferenceWithAlreadyResolvedCheckAsync(string fullJsonPath, string jsonPath) { try { string[] arr = fullJsonPath.Split(new char[1] { '#' }); if (!_resolvedSchemas.ContainsKey(arr[0])) { JsonSchema4 jsonSchema = await ResolveUrlReferenceAsync(arr[0]).ConfigureAwait(false); _schemaResolver.AppendSchema(jsonSchema, null); _resolvedSchemas[arr[0]] = jsonSchema; } JsonSchema4 jsonSchema2 = _resolvedSchemas[arr[0]]; return (arr.Length != 1) ? (await ResolveReferenceAsync(jsonSchema2, "#" + arr[1]).ConfigureAwait(false)) : jsonSchema2; } catch (Exception innerException) { throw new InvalidOperationException("Could not resolve the JSON path '" + jsonPath + "' with the full JSON path '" + fullJsonPath + "'.", innerException); } } private JsonSchema4 ResolveDocumentReference(object obj, List<string> segments, HashSet<object> checkedObjects) { if (obj == null || obj is string || checkedObjects.Contains(obj)) return null; if (segments.Count == 0) return obj as JsonSchema4; 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 { 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; } } }