JsonReferenceVisitorBase
Visitor to transform an object with JsonSchema objects.
using Namotion.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using NJsonSchema.References;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace NJsonSchema.Visitors
{
public abstract class JsonReferenceVisitorBase
{
private readonly IContractResolver _contractResolver;
protected JsonReferenceVisitorBase()
: this(new DefaultContractResolver())
{
}
protected JsonReferenceVisitorBase(IContractResolver contractResolver)
{
_contractResolver = contractResolver;
}
public virtual void Visit(object obj)
{
Visit(obj, "#", null, new HashSet<object>(), delegate {
throw new NotSupportedException("Cannot replace the root.");
});
}
protected abstract IJsonReference VisitJsonReference(IJsonReference reference, string path, string typeNameHint);
protected virtual void Visit(object obj, string path, string typeNameHint, ISet<object> checkedObjects, Action<object> replacer)
{
if (obj != null && !checkedObjects.Contains(obj)) {
checkedObjects.Add(obj);
IJsonReference jsonReference = obj as IJsonReference;
if (jsonReference != null) {
IJsonReference jsonReference2 = VisitJsonReference(jsonReference, path, typeNameHint);
if (jsonReference2 != jsonReference) {
replacer(jsonReference2);
return;
}
}
JsonSchema schema = obj as JsonSchema;
if (schema != null) {
if (schema.Reference != null)
Visit(schema.Reference, path, null, checkedObjects, delegate(object o) {
schema.Reference = (JsonSchema)o;
});
if (schema.AdditionalItemsSchema != null)
Visit(schema.AdditionalItemsSchema, path + "/additionalItems", null, checkedObjects, delegate(object o) {
schema.AdditionalItemsSchema = (JsonSchema)o;
});
if (schema.AdditionalPropertiesSchema != null)
Visit(schema.AdditionalPropertiesSchema, path + "/additionalProperties", null, checkedObjects, delegate(object o) {
schema.AdditionalPropertiesSchema = (JsonSchema)o;
});
if (schema.Item != null)
Visit(schema.Item, path + "/items", null, checkedObjects, delegate(object o) {
schema.Item = (JsonSchema)o;
});
for (int i = 0; i < schema.Items.Count; i++) {
int index = i;
Visit(schema.Items.ElementAt(i), path + "/items[" + i + "]", null, checkedObjects, delegate(object o) {
ReplaceOrDelete(schema.Items, index, (JsonSchema)o);
});
}
for (int j = 0; j < schema.AllOf.Count; j++) {
int index2 = j;
Visit(schema.AllOf.ElementAt(j), path + "/allOf[" + j + "]", null, checkedObjects, delegate(object o) {
ReplaceOrDelete(schema.AllOf, index2, (JsonSchema)o);
});
}
for (int k = 0; k < schema.AnyOf.Count; k++) {
int index3 = k;
Visit(schema.AnyOf.ElementAt(k), path + "/anyOf[" + k + "]", null, checkedObjects, delegate(object o) {
ReplaceOrDelete(schema.AnyOf, index3, (JsonSchema)o);
});
}
for (int l = 0; l < schema.OneOf.Count; l++) {
int index4 = l;
Visit(schema.OneOf.ElementAt(l), path + "/oneOf[" + l + "]", null, checkedObjects, delegate(object o) {
ReplaceOrDelete(schema.OneOf, index4, (JsonSchema)o);
});
}
if (schema.Not != null)
Visit(schema.Not, path + "/not", null, checkedObjects, delegate(object o) {
schema.Not = (JsonSchema)o;
});
if (schema.DictionaryKey != null)
Visit(schema.DictionaryKey, path + "/x-dictionaryKey", null, checkedObjects, delegate(object o) {
schema.DictionaryKey = (JsonSchema)o;
});
if (schema.DiscriminatorRaw != null)
Visit(schema.DiscriminatorRaw, path + "/discriminator", null, checkedObjects, delegate(object o) {
schema.DiscriminatorRaw = o;
});
KeyValuePair<string, JsonSchemaProperty>[] array = schema.Properties.ToArray();
for (int m = 0; m < array.Length; m++) {
KeyValuePair<string, JsonSchemaProperty> p2 = array[m];
Visit(p2.Value, path + "/properties/" + p2.Key, p2.Key, checkedObjects, delegate(object o) {
schema.Properties[p2.Key] = (JsonSchemaProperty)o;
});
}
array = schema.PatternProperties.ToArray();
for (int m = 0; m < array.Length; m++) {
KeyValuePair<string, JsonSchemaProperty> p3 = array[m];
Visit(p3.Value, path + "/patternProperties/" + p3.Key, null, checkedObjects, delegate(object o) {
schema.PatternProperties[p3.Key] = (JsonSchemaProperty)o;
});
}
KeyValuePair<string, JsonSchema>[] array2 = schema.Definitions.ToArray();
for (int m = 0; m < array2.Length; m++) {
KeyValuePair<string, JsonSchema> p4 = array2[m];
Visit(p4.Value, path + "/definitions/" + p4.Key, p4.Key, checkedObjects, delegate(object o) {
if (o != null)
schema.Definitions[p4.Key] = (JsonSchema)o;
else
schema.Definitions.Remove(p4.Key);
});
}
}
if (!(obj is string) && !(obj is JToken) && obj.GetType() != typeof(JsonSchema)) {
JsonObjectContract jsonObjectContract = _contractResolver.ResolveContract(obj.GetType()) as JsonObjectContract;
if (jsonObjectContract != null) {
foreach (JsonProperty item in jsonObjectContract.Properties.Where(delegate(JsonProperty p) {
if ((!(obj is JsonSchema) || !JsonSchema.JsonSchemaPropertiesCache.Contains(p.UnderlyingName)) && !p.Ignored)
return p.ShouldSerialize?.Invoke(obj) ?? true;
return false;
})) {
object value = item.ValueProvider.GetValue(obj);
if (value != null)
Visit(value, path + "/" + item.PropertyName, item.PropertyName, checkedObjects, delegate(object o) {
item.ValueProvider.SetValue(obj, o);
});
}
} else {
IDictionary dictionary = obj as IDictionary;
if (dictionary != null) {
object[] array3 = dictionary.Keys.OfType<object>().ToArray();
foreach (object key in array3) {
Visit(dictionary[key], path + "/" + key, key.ToString(), checkedObjects, delegate(object o) {
if (o != null)
dictionary[key] = (JsonSchema)o;
else
dictionary.Remove(key);
});
}
ContextualType contextualType = ContextualTypeExtensions.ToContextualType(obj.GetType());
if (contextualType.get_TypeAttributes().OfType<JsonConverterAttribute>().Any()) {
foreach (ContextualPropertyInfo item2 in ContextualTypeExtensions.GetContextualProperties(contextualType.get_Type()).Where(delegate(ContextualPropertyInfo p) {
if (p.get_MemberInfo().DeclaringType == contextualType.get_Type())
return !p.get_ContextAttributes().OfType<JsonIgnoreAttribute>().Any();
return false;
})) {
object value2 = item2.GetValue(obj);
if (value2 != null)
Visit(value2, path + "/" + item2.get_Name(), item2.get_Name(), checkedObjects, delegate(object o) {
item2.SetValue(obj, o);
});
}
}
} else {
IList list = obj as IList;
if (list != null) {
object[] array4 = list.OfType<object>().ToArray();
for (int n = 0; n < array4.Length; n++) {
int index5 = n;
Visit(array4[n], path + "[" + n + "]", null, checkedObjects, delegate(object o) {
ReplaceOrDelete(list, index5, o);
});
}
} else {
IEnumerable enumerable = obj as IEnumerable;
if (enumerable != null) {
object[] array5 = enumerable.OfType<object>().ToArray();
for (int num = 0; num < array5.Length; num++) {
Visit(array5[num], path + "[" + num + "]", null, checkedObjects, delegate {
throw new NotSupportedException("Cannot replace enumerable item.");
});
}
}
}
}
}
}
}
}
private void ReplaceOrDelete<T>(ICollection<T> collection, int index, T obj)
{
((Collection<T>)collection).RemoveAt(index);
if (obj != null)
((Collection<T>)collection).Insert(index, obj);
}
private void ReplaceOrDelete(IList collection, int index, object obj)
{
collection.RemoveAt(index);
if (obj != null)
collection.Insert(index, obj);
}
}
}