Reputation: 947
I have a base and derived class and I want to customize the JSON serialization/deserialization of the derived class but build on what would be serialization/deserialization in the base class. I can't see how to do this with a JsonConverter class.
Example Classes
public class MyBase
{
public long id { get; set; }
public virtual string name { get; set; }
public string desc { get; set; }
...
}
[JsonConverter(typeof(MyDerivedSerializer))]
public class MyDerived : myBase
{
public double rate { get; set; }
public double temp { get; set; }
...
}
public class MyDerivedSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var baseS = value as MyBase;
//??? How to get JSON for base class
//Add items for derived class
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
while ((reader.TokenType != JsonToken.Null) && (reader.TokenType != JsonToken.EndObject))
{
JObject jo = JObject.Load(reader);
JToken itemProps = jo["properties"];
jo.Remove("properties");
foreach (JToken c in itemProps.Children())
{
if (c.Type == JTokenType.Property)
{
JProperty p = c as JProperty;
if (!jo.ContainsKey(p.Name))
jo[p.Name] = p.Value;
}
}
}
//now that the JSON is good, how do I put the data in a created derived object
var x = Activator.CreateInstance(objectType);
return x;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
The tool using the JSON needs all the derived class properties in a sub field called "properties" but I can't change my derived classes. So I would like to just edit the JSON using the JsonConveter to look like this.
{
"id": 33,
"name": "xSource",
"desc": "Main source",
...
"properties": {
"rate": "3.21",
"temp": "245.2"
...
}
}
Upvotes: 1
Views: 1909
Reputation: 2221
You will want to clean up a bit but I got this to spit out
{"id":1,"name":"Name","desc":"Desc","properties":{"rate":2.0,"temp":3.0}}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JToken t = JToken.FromObject((MyBase)value);
JObject jo = (JObject)t;
var baseProperties =
typeof(MyBase).GetProperties(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly);
var derivedProperties =
typeof(MyDerived).GetProperties(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly);
var derivedValues = jo.Properties().Where(x => derivedProperties.Any(y => y.Name == x.Name));
var baseValues = jo.Properties().Where(x => baseProperties.Any(y => y.Name == x.Name)).ToList();
JObject o = new JObject(baseValues);
o.Add(new JProperty("properties", new JObject(derivedValues)));
o.WriteTo(writer);
}
Did have to remove the decorator from the class and move to the deseriliazation call like so was getting stackoverflow.
var result = JsonConvert.SerializeObject(test, new KeysJsonConverter());
Upvotes: 1