none
Aus der MSDN-Hotline: Json.NET benutzerdefinierter Diskriminator RRS feed

  • Allgemeine Diskussion

  • Hallo zusammen,
    heute wurde uns bei der MSDN-Entwickler-Hotline unter anderem folgende Frage gestellt:

    Ich habe folgende Klassen:

    abstract class Human
    {
        string Name { get; set; }
    }
    
    class Teacher : Human
    {
        string Subject { get; set; }
    }
    
    class Pupil : Human
    {
        string AttendedClass { get; set; }
    }
    
    class Document
    {
        public Human[] Items { get; set; }
    }

    und möchte folgende JSON-Struktur darauf abbilden:

    {
        "items": [
            {
                "type": "teacher",
                "name": "Max Mustermann",
                "subject":  "Computer Science"
            },
            {
                "type": "pupil",
                "name":  "John Doe",
                "attendedClass":  "11n"
            }
        ]
    }

    Dabei soll die Eigenschaft "type" angeben, ob es sich dabei um einen Lehrer oder Schüler handelt, je nachdem ob der Wert "teacher" oder "pupil" ist. Wie kann ich das möglichst einfach erreichen?

    Unsere Antwort bzw. unser Lösungsvorschlag darauf war:

    Json.NET ist eine Bibliothek, die das Serialisieren sowie Deserialisieren von Json-Dokumenten stark vereinfacht. Allerdings unterstützt sie von Haus aus nicht die Verwendung eines benutzerdefinierten Diskriminators. Der Diskriminator ist eine Eigenschaft, die verwendet wird, um verschiedene Typen zu trennen. In diesem Fall ist der Diskriminator die Eigenschaft "type", wobei die Ausprägung "teacher" auf die Klasse "Teacher" und "pupil" auf die Klasse "Pupil" abgebildet werden soll.

    Json.NET lässt sich aber mithilfe eines benutzerdefinierten JsonConverters dahingehend erweitern, sodass dieses Verhalten unterstützt wird.

    Die Klasse "CustomDiscriminatorObjectConverter" kann unter [1] gefunden werden und unterstützt die Verwendung eines benutzerdefinierten Diskriminators, indem ein neuer JsonConverter bereitgestellt wird.

    Mit Json.NET und der genannten Klasse kann das JSON-Dokument wie folgt deserialisiert werden:

    var settings = new JsonSerializerSettings();
    settings.Converters.Add(new CustomDiscriminatorObjectConverter());
    Document result = JsonConvert.DeserializeObject<Document>(File.ReadAllText("data.json"), settings);

    Wobei die Klassen noch wie folgt annotiert werden müssen:

    [DiscriminatedClass("type")]
    [DiscriminatedSubtype("pupil", typeof(Pupil))]
    [DiscriminatedSubtype("teacher", typeof(Teacher))]
    abstract class Human
    {
        [JsonProperty]
        string Name { get; set; }
    }
    
    class Teacher : Human
    {
        [JsonProperty]
        string Subject { get; set; }
    }
    
    class Pupil : Human
    {
        [JsonProperty]
        string AttendedClass { get; set; }
    }
    
    class Document
    {
        [JsonProperty]
        public Human[] Items { get; set; }
    }

    Das Attribut "DiscriminatedClass" spezifiziert die Eigenschaft, die als Diskriminator verwendet werden soll. Das Attribut "DiscriminatedSubtype" gibt an, welche Klasse für eine bestimmte Ausprägung des Diskriminators verwendet werden soll.

    [1] https://gist.github.com/hediet/3db87d8f39c22ffee9de

    Wir hoffen, vielen Besuchern der MSDN Foren durch das Posten dieses Problems und einer möglichen Lösung weiterhelfen zu können.

    Viele Grüße,

    Entwickler-Hotline für MSDN Online Deutschland

    Disclaimer:
    Bitte haben Sie Verständnis dafür, dass wir hier auf Rückfragen gar nicht oder nur sehr zeitverzögert antworten können.
    Bitte nutzen Sie für Rückfragen oder neue Fragen den telefonischen Weg über die MSDN-Entwickler-Hotline: http://www.msdn-online.de/Hotline
    MSDN-Entwickler-Hotline: Schnelle & kompetente Hilfe für Entwickler: kostenfrei!

    Es gelten für die MSDN-Entwickler-Hotline und dieses Posting diese Nutzungsbedingungen , Hinweise zu Markenzeichen, Informationen zur Datensicherheit sowie die gesonderten Nutzungsbedingungen für die MSDN-Entwickler-Hotline .

    Dienstag, 10. März 2015 12:55