Десериализация неоднозначного JSON - PullRequest
4 голосов
/ 16 февраля 2011
public abstract class A {
    public string Foo{ get; set; }
}

public class B : A {
    public string Marco{ get; set; }
}

public class C : A {
    public string Las{ get; set; }
}

public class D : A {
    public string Las{ get; set; }
}

public class SerializeMe {
    [XmlElement("b", typeof(B))]
    [XmlElement("c", typeof(C))]
    [XmlElement("d", typeof(D))]
    public A[] serializeProp { get; set; }
}

SerializeMe me = new SerializeMe();
me.serializeProp = new A[]{
                           new B(){ Foo = "bar", Marco = "polo" },
                           new C(){ Foo = "bar", Las = "Vegas" },
                           new D(){ Foo = "bar", Las = "Vegas" }
                          };

Атрибуты XmlElement управляют сериализацией xml, так что это приводит к:

 <SerializeMe>
    <B><Foo>bar</Foo><Marco>polo</Marco></B>
    <C><Foo>bar</Foo><Las>Vegas</Las></C>
    <D><Foo>bar</Foo><Las>Vegas</Las></D>
 </SerializeMe>

И если бы я должен был добавить подобные атрибуты для десериализации в json (используя библиотеку Newtonsoft Json.Net):

{[
    {"Foo":"bar", "Marco":"polo"},
    {"Foo":"bar", "Las":"Vegas"},
    {"Foo":"bar", "Las":"Vegas"}
]}

Однако, в отличие от xml, он не содержит деталей о типах, поэтому для меня не очевидно, что он будет правильно определять, в какой класс десериализоваться.Есть ли в любом случае правильная десериализация с использованием существующей структуры json, или мне нужно изменить структуру json (и как лучше это сделать).

Я подумал о переопределении сериализации, чтобы она выглядела следующим образом:

{[
    {"class":"B",
     "object":{"Foo":"bar", "Marco":"polo"}},
    {"class":"C",
     "object":{"Foo":"bar", "Las":"Vegas"}},
    {"class":"D",
     "object":{"Foo":"bar", "Las":"Vegas"}}
]}

Есть ли лучший способ?

1 Ответ

2 голосов
/ 16 февраля 2011

Вы можете опустить вложенный "object"= и просто использовать строку, которая не является допустимым именем свойства, в качестве идентификатора класса:

{"Foo":"bar", "Marco":"polo", "$Class"="B"}

JSON.net имеет встроенную функцию TypeNameHandling, сгенерированный json выглядит следующим образом:

{"$type":"Tests.MessageWrapper2, Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Headers":{"$type":"System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089","DeliverAt":"yesterday!"},
"Body":{"$type":"Tests.TestMessage1, Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Id":893239}
}

Обратите внимание, что если вы используете TypeNameHandling, json может создавать произвольные типы. Так что вы можете не захотеть десериализовать JSON из ненадежного источника.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...