JsonPathUtilities
Utilities to work with JSON paths.
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
namespace NJsonSchema
{
public static class JsonPathUtilities
{
public static string GetJsonPath(object obj, object objectToSearch)
{
string jsonPath = GetJsonPath(obj, objectToSearch, "#", new List<object>());
if (jsonPath == null)
throw new InvalidOperationException("Could not resolve the path.");
return jsonPath;
}
public static JsonSchema4 GetObjectFromJsonPath(object obj, string path)
{
if (path == "#") {
if (obj is JsonSchema4)
return (JsonSchema4)obj;
throw new InvalidOperationException("Could not resolve the path.");
}
if (path.StartsWith("#/")) {
JsonSchema4 objectFromJsonPath = GetObjectFromJsonPath(obj, path.Split(new char[1] {
'/'
}).Skip(1).ToList(), new List<object>());
if (objectFromJsonPath == null)
throw new InvalidOperationException("Could not resolve the path '" + path + "'.");
return objectFromJsonPath;
}
if (path.StartsWith("http://") || path.StartsWith("https://"))
throw new NotSupportedException("Could not resolve the path '" + path + "' because JSON web references are not supported.");
throw new NotSupportedException("Could not resolve the path '" + path + "' because JSON file references are not supported.");
}
public static string GetPropertyName(PropertyInfo property)
{
JsonPropertyAttribute customAttribute = property.GetCustomAttribute<JsonPropertyAttribute>();
if (customAttribute != null && !string.IsNullOrEmpty(customAttribute.PropertyName))
return customAttribute.PropertyName;
if (property.DeclaringType.GetTypeInfo().GetCustomAttribute<DataContractAttribute>() != null) {
DataMemberAttribute customAttribute2 = property.GetCustomAttribute<DataMemberAttribute>();
if (customAttribute2 != null && !string.IsNullOrEmpty(customAttribute2.Name))
return customAttribute2.Name;
}
return property.Name;
}
private static string GetJsonPath(object obj, object objectToSearch, string basePath, List<object> checkedObjects)
{
if (obj == null || obj is string || checkedObjects.Contains(obj))
return null;
if (obj == objectToSearch)
return basePath;
checkedObjects.Add(obj);
if (obj is IDictionary) {
foreach (object key in ((IDictionary)obj).Keys) {
string jsonPath = GetJsonPath(((IDictionary)obj)[key], objectToSearch, basePath + "/" + key, checkedObjects);
if (jsonPath != null)
return jsonPath;
}
} else if (obj is IEnumerable) {
int num = 0;
foreach (object item in (IEnumerable)obj) {
string jsonPath2 = GetJsonPath(item, objectToSearch, basePath + "/" + num, checkedObjects);
if (jsonPath2 != null)
return jsonPath2;
num++;
}
} else {
foreach (PropertyInfo item2 in from p in obj.GetType().GetRuntimeProperties()
where p.GetCustomAttribute<JsonIgnoreAttribute>() == null
select p) {
string propertyName = GetPropertyName(item2);
object value = item2.GetValue(obj);
if (value != null) {
string jsonPath3 = GetJsonPath(value, objectToSearch, basePath + "/" + propertyName, checkedObjects);
if (jsonPath3 != null)
return jsonPath3;
}
}
}
return null;
}
private static JsonSchema4 GetObjectFromJsonPath(object obj, List<string> segments, List<object> checkedObjects)
{
if (obj == null || obj is string || checkedObjects.Contains(obj))
return null;
if (segments.Count == 0)
return (JsonSchema4)obj;
checkedObjects.Add(obj);
if (obj is IDictionary) {
if (((IDictionary)obj).Contains(segments.First()))
return GetObjectFromJsonPath(((IDictionary)obj)[segments.First()], segments.Skip(1).ToList(), checkedObjects);
} else if (obj is IEnumerable) {
if (int.TryParse(segments.First(), out int result)) {
object[] array = ((IEnumerable)obj).Cast<object>().ToArray();
if (array.Length > result)
return GetObjectFromJsonPath(array[result], segments.Skip(1).ToList(), checkedObjects);
}
} else {
foreach (PropertyInfo item in from p in obj.GetType().GetRuntimeProperties()
where p.GetCustomAttribute<JsonIgnoreAttribute>() == null
select p) {
string propertyName = GetPropertyName(item);
object value = item.GetValue(obj);
if (propertyName == segments.First())
return GetObjectFromJsonPath(value, segments.Skip(1).ToList(), checkedObjects);
}
}
return null;
}
}
}