Custom JsonConverter WriteJson Does Not Alter Serialization of Sub-properties Custom JsonConverter WriteJson Does Not Alter Serialization of Sub-properties json json

Custom JsonConverter WriteJson Does Not Alter Serialization of Sub-properties


The reason that your converter is not getting applied to your child objects is because JToken.FromObject() uses a new instance of the serializer internally, which does not know about your converter. There is an overload that allows you to pass in the serializer, but if you do so here you will have another problem: since you are inside a converter and you are using JToken.FromObject() to try to serialize the parent object, you will get into an infinite recursive loop. (JToken.FromObject() calls the serializer, which calls your converter, which calls JToken.FromObject(), etc.)

To get around this problem, you must handle the parent object manually. You can do this without much trouble using a bit of reflection to enumerate the parent properties:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){    JObject jo = new JObject();    Type type = value.GetType();    jo.Add("type", type.Name);    foreach (PropertyInfo prop in type.GetProperties())    {        if (prop.CanRead)        {            object propVal = prop.GetValue(value, null);            if (propVal != null)            {                jo.Add(prop.Name, JToken.FromObject(propVal, serializer));            }        }    }    jo.WriteTo(writer);}

Fiddle: https://dotnetfiddle.net/sVWsE4


Here's an idea, instead of doing the reflection on every property, iterate through the normally serialized JObject and then changed the token of properties you're interested in.

That way you can still leverage all the ''JsonIgnore'' attributes and other attractive features built-in.

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){    JToken jToken = JToken.FromObject(value);    if (jToken.Type == JTokenType.Object)    {        JObject jObject = (JObject)jToken;        ...        AddRemoveSerializedProperties(jObject, val);        ...    }    ...}

And then

private void AddRemoveSerializedProperties(JObject jObject, MahMan baseContract)   {       jObject.AddFirst(....);        foreach (KeyValuePair<string, JToken> propertyJToken in jObject)        {            if (propertyJToken.Value.Type != JTokenType.Object)                continue;            JToken nestedJObject = propertyJToken.Value;            PropertyInfo clrProperty = baseContract.GetType().GetProperty(propertyJToken.Key);            MahMan nestedObjectValue = clrProperty.GetValue(baseContract) as MahMan;            if(nestedObj != null)                AddRemoveSerializedProperties((JObject)nestedJObject, nestedObjectValue);        }    }


I had this issue using two custom converters for a parent and child type. A simpler method I found is that since an overload of JToken.FromObject() takes a serializer as a parameter, you can pass along the serializer you were given in WriteJson(). However you need to remove your converter from the serializer to avoid a recursive call to it (but add it back in after):

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){    serializer.Converters.Remove(this);    JToken jToken = JToken.FromObject(value, serializer);    serializer.Converters.Add(this);    // Perform any necessary conversions on the object returned}