C# JSON 的自动属性反序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/945585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:57:40  来源:igfitidea点击:

C# automatic property deserialization of JSON

c#.netjsonserializationautomatic-properties

提问by Tamas Czinege

I need to deserialize some JavaScript object represented in JSON to an appropriate C# class. Given the nice features of automatic properties, I would prefer having them in these classes as opposed to just having fields. Unfortunately, the .NET serialization engine (at least, by default) totally ignores automatic properties on deserialization and only cares about the backing field, which is obviously not present in the JavaScript object.

我需要将一些以 JSON 表示的 JavaScript 对象反序列化为适当的 C# 类。鉴于自动属性的良好特性,我更喜欢将它们包含在这些类中,而不是仅仅包含字段。不幸的是,.NET 序列化引擎(至少在默认情况下)完全忽略反序列化的自动属性,只关心支持字段,这显然不存在于 JavaScript 对象中。

Given that there's no standard way to name backing fieldsand to be honest I don't even want to bother with the "let's create a JavaScript object that looks like it had C# backing fields" approach as it sounds a bit dirty, the only way I could serialize JavaScript fields to C# auto-properties if I could force the serialization engine to somehow ignore the backing field and use the property directly. Unfortunately, I can't figure out how this is done or if this can be done at all. Any ideas would be appreciated.

鉴于没有标准的方法来命名支持字段,老实说,我什至不想打扰“让我们创建一个看起来像有 C# 支持字段的 JavaScript 对象”的方法,因为它听起来有点脏,唯一的方法如果我可以强制序列化引擎以某种方式忽略支持字段并直接使用属性,我可以将 JavaScript 字段序列化为 C# 自动属性。不幸的是,我无法弄清楚这是如何完成的,或者是否可以完成。任何想法,将不胜感激。

EDIT: Here's an example:

编辑:这是一个例子:

Javascript:

Javascript:

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

This is then serialized to "{Name: 'Whiskers'}".

然后将其序列化为“{Name: 'Whiskers'}”。

The C# class:

C# 类:

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

And the deserialization code, that fails:

以及失败的反序列化代码:

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

And it is apparent from the exception that it fails because it is looking for the backing field.

从异常中可以明显看出它失败了,因为它正在寻找支持字段。

EDIT2: Here's the exception, if that helps (no inner exceptions):

EDIT2:这是例外,如果有帮助的话(没有内部例外):

System.Runtime.Serialization.SerializationException

"The data contract type 'Test.Cat' cannot be deserialized because the required data members '<Name>k__BackingField, <Breed>k__BackingField' were not found."

System.Runtime.Serialization.SerializationException

“无法反序列化数据协定类型‘Test.Cat’,因为<Name>k__BackingField, <Breed>k__BackingField找不到所需的数据成员‘ ’。”

采纳答案by baretta

What's happening here is the deserializer is trying to guess the name of your backing fields. You can solve this by adding explicit mappings (DataContract/DataMember attributes) like this:

这里发生的事情是反序列化器试图猜测您的支持字段的名称。您可以通过添加显式映射(DataContract/DataMember 属性)来解决这个问题,如下所示:

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

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

回答by aleemb

You can do this with JavaScriptSerializerfound in the System.Web.Script.Serializationnamespace:

您可以使用命名空间中的JavaScriptSerializerfound来做到这一点System.Web.Script.Serialization

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

I have POCO objects with automatic properties and this works just fine.

我有具有自动属性的 POCO 对象,这很好用。

EDIT: I wrote about JSON Serializers in .NETwhich compares this serializer with DataContractJsonSerializer.

编辑:我在 .NET 中写了关于JSON Serializers 的文章,它将这个序列化器与DataContractJsonSerializer.

回答by Chris Brandsma

I'm assuming you are passing data via a web service. If you are using the WebService class with the ScriptMethod attribute uncommented-out, the web service methods can read JSON natively. They even use the same JavaScriptSerializer that was mentioned above. If you are using WCF I'm a little more fuzzy on the logic.

我假设您正在通过 Web 服务传递数据。如果您使用 WebService 类的 ScriptMethod 属性未注释,则 Web 服务方法可以本机读取 JSON。他们甚至使用上面提到的相同的 JavaScriptSerializer。如果您使用 WCF,我对逻辑有点模糊。

But make sure your JSON object are returning data for EVERY property in your class. In your error, there is mention of a Breed property that is not in your example.

但请确保您的 JSON 对象正在返回您班级中每个属性的数据。在您的错误中,提到了您的示例中没有的 Breed 属性。

Also, on the JavaScript side, do to the dynamic nature of JavaScript it is easy to add new properties to your objects. This can sometimes lead to circular references. You should remove any extra data that you might have added (just as you are sending data via the web method, then add it again once you are done).

此外,在 JavaScript 方面,根据 JavaScript 的动态特性,向对象添加新属性很容易。这有时会导致循环引用。您应该删除您可能添加的任何额外数据(就像您通过网络方法发送数据一样,然后在完成后再次添加)。

回答by amelvin

baretta's answersolved the k__BackingField bloat for me. Just a tiny addendum that you can decorate this class to auto serialize into either XML or JSON in a similar way:

baretta 的回答为我解决了 k__BackingField 膨胀。只是一个小小的附录,你可以装饰这个类以类似的方式自动序列化为 XML 或 JSON:

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

... and then use a DataContractJsonSerializer or XmlSerializer to prepare it for your endpoint.

...然后使用 DataContractJsonSerializer 或 XmlSerializer 为您的端点准备它。