Search code examples
c#serializationjson.net

How to serialize object to json with type info using Newtonsoft.Json?


I want to have a property with type name in JSON when I serialize objects of certain types. I wrote a converter:

public class TypeInfoConverter : JsonConverter {
    private readonly IEnumerable<Type> _types;

    public TypeInfoConverter(IEnumerable<Type> types) {
        Contract.Requires(types != null);

        _types = types;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        var jObject = JObject.FromObject(value, serializer);
        jObject.AddFirst(new JProperty("Type", value.GetType().Name));
        jObject.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        return serializer.Deserialize(reader, objectType);
    }

    public override bool CanConvert(Type objectType) {
        return _types.Any(t => t.IsAssignableFrom(objectType));
    }
}

But when I'm trying to serialize object I have an infinity recursion here: var jObject = JObject.FromObject(value, serializer); It is obvious because I use the same instance of JsonSerializer which was configured with that converter.

How to prevent using this converter, but I want to use other converters which configured for this serializer?

Types which I want to serialize:

public interface ITaskResult {
}

public class UserHasRejectedOffer : ITaskResult {
    public string Message { get; set; }
}

public class UserHasFilledForm : ITaskResult {
    public string FormValue1 { get; set; }

    public string Formvalue2 { get; set; }
}

...

Solution

  • public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
        var converters = serializer.Converters.Where(x => !(x is TypeInfoConverter)).ToArray();
    
        var jObject = JObject.FromObject(value);
        jObject.AddFirst(new JProperty("Type", value.GetType().Name));
        jObject.WriteTo(writer, converters);
    }