Deserializador personalizado solo para algunos campos con json.NET

Deserializador personalizado solo para algunos campos con json.NET

Dado que está anotando su tipo con atributos Json.NET de todos modos, una solución más simple parecería ser colocar los convertidores en las propiedades relevantes usando [JsonConverter(Type)] o [JsonProperty(ItemConverterType = Type)] :

public class Configuration
{
    public int a { get; set; }
    public int b { get; set; }
    public Obj1 obj1 { get; set; }

    // Converts the entire list to a compressed string
    [JsonConverter(typeof(IntListConverter))]
    public int[] c { get; set; }

    // Converts each Obj2 item individually
    [JsonProperty(ItemConverterType = typeof(Obj2Converter))]
    public IList<Obj2> obj2 { get; set; }
}

Sin embargo, si necesita conservar el convertidor en Configuration (o en realidad están agregando el convertidor a JsonSerializerSettings.Converters y no puede agregar atributos Json.NET a su tipo), puede usar JsonSerializer.Populate() para completar las propiedades estándar, siempre que primero elimine las propiedades personalizadas del JObject :

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        var jsonObject = JObject.Load(reader);

        var configuration = (existingValue as Configuration ?? new Configuration());

        // I created the JsonConverter for those 2 properties
        configuration.c = myCustomProcessMethod(jsonObject["c"].RemoveFromLowestPossibleParent());
        configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].RemoveFromLowestPossibleParent().ToObject<ValletConfiguration>());

        // Populate the remaining standard properties
        using (var subReader = jsonObject.CreateReader())
        {
            serializer.Populate(subReader, configuration);
        }

        return configuration;
    }

Usando el método de extensión:

public static class JsonExtensions
{
    public static JToken RemoveFromLowestPossibleParent(this JToken node)
    {
        if (node == null)
            return null;
        var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
        if (contained != null)
            contained.Remove();
        // Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
        if (node.Parent is JProperty)
            ((JProperty)node.Parent).Value = null;
        return node;
    }
}

Una forma posible es crear una propiedad de proxy para serializar y deserializar correctamente. Al usar ScriptIgnoreAttribute (también es posible JsonIgnoreAttribute), la propiedad real no se serializa. Aquí hay un ejemplo:

[ScriptIgnore]
public int RealProperty { get; set; }

public string RealPropertyProxy
{
    get
    {
        return SerializeRealProperty(RealProperty);
    }
    set
    {
        RealProperty = DeserializeRealProperty(value);
    }
}

El resultado es que solo el proxy se serializa de la forma en que lo definió (según el valor de la propiedad real). Simplemente modifique las propiedades necesarias para ser serializadas de una manera especial y no necesita implementar un JsonConverter especial .