Skip to content

Instantly share code, notes, and snippets.

@flakey-bit
Last active July 19, 2018 03:44
Show Gist options
  • Save flakey-bit/825b776d8255733835a7b4351529f58e to your computer and use it in GitHub Desktop.
Save flakey-bit/825b776d8255733835a7b4351529f58e to your computer and use it in GitHub Desktop.
Deserialize recursive subclasses via enum w/ Json.NET (Newtownsoft.JSON)
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Questionaire
{
internal class QuestionaireNodeConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (!IsAbstractDecendantOf<QuestionaireNode>(objectType))
{
serializer.ContractResolver.ResolveContract(objectType).Converter = null;
return serializer.Deserialize(reader, objectType);
}
var jObject = JObject.Load(reader);
var nodeTypeValue = jObject.Value<string>("type");
var nodeType = nodeTypeValue.ToEnum<QuestionareNodeType>();
Type nodeImplType;
switch (nodeType)
{
case QuestionareNodeType.RadioGroup:
nodeImplType = typeof(RadioGroupNode);
break;
case QuestionareNodeType.CalculatedField:
nodeImplType = typeof(CalculatedFieldNode);
break;
case QuestionareNodeType.Currency:
nodeImplType = typeof(CurrencyNode);
break;
case QuestionareNodeType.Date:
nodeImplType = typeof(DateNode);
break;
case QuestionareNodeType.FileUpload:
nodeImplType = typeof(FileUploadNode);
break;
case QuestionareNodeType.Heading:
nodeImplType = typeof(HeadingNode);
break;
case QuestionareNodeType.MultipleColumns:
nodeImplType = typeof(MultipleColumnsNode);
break;
case QuestionareNodeType.MultiSelect:
nodeImplType = typeof(MultiSelectNode);
break;
case QuestionareNodeType.Number:
nodeImplType = typeof(NumberNode);
break;
case QuestionareNodeType.Percentage:
nodeImplType = typeof(PercentageNode);
break;
case QuestionareNodeType.Repeater:
nodeImplType = typeof(RepeaterNode);
break;
case QuestionareNodeType.Select:
nodeImplType = typeof(SelectNode);
break;
case QuestionareNodeType.Tab:
nodeImplType = typeof(TabNode);
break;
case QuestionareNodeType.Text:
nodeImplType = typeof(TextNode);
break;
case QuestionareNodeType.TextArea:
nodeImplType = typeof(TextAreaNode);
break;
default:
throw new ArgumentOutOfRangeException();
}
return serializer.Deserialize(jObject.CreateReader(), nodeImplType);
}
public override bool CanConvert(Type objectType)
{
return IsAbstractDecendantOf<QuestionaireNode>(objectType);
}
public override bool CanWrite => false;
private bool IsAbstractDecendantOf<T>(Type instanceType)
{
return typeof(T).IsAssignableFrom(instanceType) && instanceType.IsAbstract;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment