【问题标题】:C# automatic property deserialization of JSONJSON的C#自动属性反序列化
【发布时间】:2010-10-31 01:01:31
【问题描述】:

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

鉴于有 no standard way to name backing fields,老实说,我什至不想打扰“让我们创建一个看起来像具有 C# 支持字段的 JavaScript 对象”方法,因为这听起来有点脏,这是我唯一的方法如果我可以强制序列化引擎以某种方式忽略支持字段并直接使用该属性,则可以将 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' 不是 找到了。”

【问题讨论】:

  • 你能举个例子说明你的意思吗?
  • @John Saunders - 假设我有一个名为“Cat”的 JavaScript 对象,其中有一个名为“Name”的字段,其值为“Whiskers”。假设这是用 JSON 表示的。我想获取这个 JSON 并将其序列化为 C# Cat 类的实例(由我编写),以便序列化过程用“Whiskers”填充实例的自动属性“Name”。
  • ...但问题是序列化程序正在寻找支持字段(例如“k_backingField”但不一定使用此名称“)而不是“名称”。
  • 你用的是什么序列化器?
  • 另外,我没用过这个,但也许你应该使用 [DataContract] 和 [DataMember] 而不是 [Serializable]?

标签: c# .net json serialization automatic-properties


【解决方案1】:

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

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

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

【讨论】:

  • +1 我回答的第一个问题,但当时我没有代表支持这个答案!
  • 如果可以的话,我会 +2。暂时寻找这个问题的答案。
  • 超级!我错过了 [DataContract] 属性:(
【解决方案2】:

您可以使用位于 System.Web.Script.Serialization 命名空间中的 JavaScriptSerializer 来执行此操作:

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

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

编辑:我写了关于 JSON Serializers in .NET 的文章,它将这个序列化程序与 DataContractJsonSerializer 进行了比较。

【讨论】:

【解决方案3】:

baretta's 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】:

    我假设您通过网络服务传递数据。如果您使用未注释掉 ScriptMethod 属性的 WebService 类,则 Web 服务方法可以原生读取 JSON。他们甚至使用上面提到的相同的 JavaScriptSerializer。如果您使用的是 WCF,我的逻辑会更加模糊。

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

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

    【讨论】:

    • 不,很遗憾,这不是网络服务。这是一个简单的ajax请求,将json中的数据传递给服务器。另外,我很确定没有循环引用。没错,在示例中没有品种属性,但在我的真实代码中,所有属性都在那里。不过感谢您的建议:)
    • 在 JavaScript 方面:您如何将 JavaScript 对象转换为 JSON?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多