Benutzerdefinierter Deserializer nur für einige Felder mit json.NET

Benutzerdefinierter Deserializer nur für einige Felder mit json.NET

Da Sie Ihren Typ sowieso mit Json.NET-Attributen annotieren, scheint eine einfachere Lösung darin zu bestehen, die Konverter mit [JsonConverter(Type)] auf die relevanten Eigenschaften zu setzen oder [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; }
}

Falls Sie dennoch den Konverter auf Configuration belassen müssen (oder fügen den Konverter tatsächlich zu JsonSerializerSettings.Converters hinzu und kann Ihrem Typ keine Json.NET-Attribute hinzufügen), können Sie JsonSerializer.Populate() verwenden um die Standardeigenschaften aufzufüllen, solange Sie zuerst die benutzerdefinierten Eigenschaften aus JObject entfernen :

    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;
    }

Verwenden der Erweiterungsmethode:

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;
    }
}

Eine Möglichkeit besteht darin, eine Proxy-Eigenschaft zu erstellen, um korrekt zu serialisieren und zu deserialisieren. Durch die Verwendung des ScriptIgnoreAttribute (möglich ist auch das JsonIgnoreAttribute) wird die reale Eigenschaft nicht serialisiert. Hier ist ein Beispiel:

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

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

Das Ergebnis ist, dass nur der Proxy so serialisiert wird, wie Sie ihn definiert haben (basierend auf dem Wert der realen Eigenschaft). Ändern Sie einfach die zu serialisierenden Eigenschaften auf eine spezielle Weise und Sie müssen keinen speziellen JsonConverter implementieren .