C # автоматическая десериализация свойств JSON - PullRequest
49 голосов
/ 03 июня 2009

Мне нужно десериализовать некоторый объект JavaScript, представленный в JSON, в соответствующий класс C #. Учитывая приятные возможности автоматических свойств, я бы предпочел иметь их в этих классах, а не просто иметь поля. К сожалению, механизм сериализации .NET (по крайней мере, по умолчанию) полностью игнорирует автоматические свойства при десериализации и заботится только о поле поддержки, которое явно отсутствует в объекте JavaScript.

Учитывая, что не существует стандартного способа именования вспомогательных полей , и, честно говоря, я даже не хочу беспокоиться о том, что "давайте создадим объект JavaScript, который выглядит так, как будто он имеет вспомогательные поля C #", как это звучит немного грязно, единственный способ, которым я мог бы сериализовать поля JavaScript в авто-свойства C #, если бы я мог заставить механизм сериализации как-то игнорировать поле поддержки и использовать свойство напрямую. К сожалению, я не могу понять, как это делается или вообще можно ли это сделать. Любые идеи будут оценены.

РЕДАКТИРОВАТЬ : Вот пример:

Javascript:

function Cat()
{
    this.Name = "Whiskers";
    this.Breed = "Tabby";
}
var cat = new Cat();

Затем он сериализуется в "{Name: 'Whiskers'}".

Класс C #:

[Serializable()]
public class Cat
{
    public string Name { get; set; }
    public string Breed { get; set; }
}

И код десериализации, который терпит неудачу:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);

И из исключения видно, что он терпит неудачу, потому что ищет поле поддержки.

EDIT2 : Вот исключение, если это помогает (без внутренних исключений):

System.Runtime.Serialization.SerializationException

"Тип контракта данных 'Test.Cat' не может быть десериализовано, потому что обязательные члены данных «<Name>k__BackingField, <Breed>k__BackingField» не было найден ".

Ответы [ 4 ]

80 голосов
/ 03 июня 2009

Здесь происходит то, что десериализатор пытается угадать название ваших вспомогательных полей. Вы можете решить эту проблему, добавив явные сопоставления (атрибуты DataContract / DataMember), например:

[DataContract]
public class Cat
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Breed { get; set; }
}
20 голосов
/ 03 июня 2009

Вы можете сделать это с JavaScriptSerializer, найденным в пространстве имен System.Web.Script.Serialization:

JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);

У меня есть объекты POCO с автоматическими свойствами, и это прекрасно работает.

EDIT: я писал о сериализаторах JSON в .NET , в которых этот сериализатор сравнивается с DataContractJsonSerializer.

5 голосов
/ 29 января 2010

ответ Баретты решил проблему с кляпом k__BackingField для меня. Просто крошечное дополнение, которое вы можете украсить этот класс для автоматической сериализации в XML или JSON аналогичным образом:

[Serializable, XmlRoot, DataContract]
public class Cat
{
  [XmlElement]
  [DataMember]
  public string Name { get; set; }
  [XmlElement]
  [DataMember]
  public string Breed { get; set; }
}

... и затем используйте DataContractJsonSerializer или XmlSerializer, чтобы подготовить его для конечной точки.

1 голос
/ 03 июня 2009

Я предполагаю, что вы передаете данные через веб-сервис. Если вы используете класс WebService с незакомментированным атрибутом ScriptMethod, методы веб-службы могут считывать данные в формате JSON. Они даже используют тот же JavaScriptSerializer, который был упомянут выше. Если вы используете WCF, я немного размышляю над логикой.

Но убедитесь, что ваш объект JSON возвращает данные для КАЖДОГО свойства вашего класса. В вашей ошибке упоминается свойство Breed, которого нет в вашем примере.

Кроме того, со стороны JavaScript, для динамической природы JavaScript легко добавлять новые свойства к вашим объектам. Иногда это может привести к циркулярным ссылкам. Вам следует удалить любые дополнительные данные, которые вы могли добавить (так же, как вы отправляете данные через веб-метод, а затем добавьте их снова, как только закончите).

...