Автоматическая десериализация свойств С#
Мне нужно десериализовать некоторый объект 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
' не были найдено".
Ответы
Ответ 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, легко добавить новые свойства к вашим объектам. Иногда это может привести к циклическим ссылкам. Вы должны удалить дополнительные данные, которые вы могли бы добавить (точно так же, как вы отправляете данные через веб-метод, а затем добавьте их снова, как только вы закончите).