Подтвердить что ты не робот

Автоматическая десериализация свойств С#

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

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

EDIT. Здесь приведен пример:

JavaScript:

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

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

Класс С#:

[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' не были найдено".

4b9b3361

Ответ 1

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

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

    [DataMember]
    public string Breed { get; set; }
}

Ответ 2

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

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

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

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

Ответ 3

baretta answer разрешил для меня раздувание 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, чтобы подготовить его к вашей конечной точке.

Ответ 4

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

Но убедитесь, что ваш объект JSON возвращает данные для свойства EVERY в вашем классе. В вашей ошибке упоминается свойство породы, которое отсутствует в вашем примере.

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