Having that:
public interface ITerm
{
string Name { get; }
}
public class Value : ITerm...
public class Variable : ITerm...
public class Query
{
public IList<ITerm> Terms { get; }
...
}
I managed conversion trick implementing that:
public class TermConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var field = value.GetType().Name;
writer.WriteStartObject();
writer.WritePropertyName(field);
writer.WriteValue((value as ITerm)?.Name);
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var properties = jsonObject.Properties().ToList();
var value = (string) properties[0].Value;
return properties[0].Name.Equals("Value") ? (ITerm) new Value(value) : new Variable(value);
}
public override bool CanConvert(Type objectType)
{
return typeof (ITerm) == objectType || typeof (Value) == objectType || typeof (Variable) == objectType;
}
}
It allows me to serialize and deserialize in JSON like:
string JsonQuery = "{\"Terms\":[{\"Value\":\"This is \"},{\"Variable\":\"X\"},{\"Value\":\"!\"}]}";
...
var query = new Query(new Value("This is "), new Variable("X"), new Value("!"));
var serializeObject = JsonConvert.SerializeObject(query, new TermConverter());
Assert.AreEqual(JsonQuery, serializeObject);
...
var queryDeserialized = JsonConvert.DeserializeObject<Query>(JsonQuery, new TermConverter());