I am trying to solve backward compartibility when deserializing old json. Previously there was double
property and now it's changed to a custom type.
My idea is to read double
and simply convert it using custom json converter.
Before was:
public class A
{
[JsonProperty)]
string Name { get; set; }
[JsonProperty)]
double Value { get; set; }
}
Serialized as
{"Name":"test","Value":33.0}
New one:
public class A
{
[JsonProperty]
[JsonConverter(typeof(MyJsonConverter))]
public MyType Value { get; set; }
}
Serialized as
{"Value":{"Value":33.0,"Name":"test", ...}},
Converter:
public class MyJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value is double value)
return new MyType(value, ???); // here is the problem, I need Name value here
return reader.Value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
JToken.FromObject(value).WriteTo(writer);
}
but to construct MyType
I need string parameter which is a value of another property Name
How to access Name
value from converter for Value
? How to access anything what has been deserialized? Is there some kind of tree? Tokens tree?
Another thing: in WriteJson
method I want to do "nothing" special, is my implementation correct? Or is there an easy way to prevent converter doing anything "special" upon serialization?
You would need to apply a converter to your parent A
class:
[JsonConverter(typeof(MyJsonConverter))]
public class A
{
public MyType Value { get; set; }
}
public class AConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(A);
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
// Check if the keys contains "Name"
string name = jObject["Name"]?.ToString();
var a = new A();
if (name != null)
{
a.Value = new MyType
{
Name = name,
Value = jObject["Value"].Value<double>()
};
}
else
{
a.Value = jObject["Value"].ToObject<MyType>();
}
return a;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
To use default serailisation, just override CanWrite
with false
.