反序列化时如何从json中删除k__BackingField

Posted

技术标签:

【中文标题】反序列化时如何从json中删除k__BackingField【英文标题】:How to remove k__BackingField from json when Deserialize 【发布时间】:2012-10-12 21:33:38 【问题描述】:

在将 xml 文件序列化为 .net c# 对象后,我在返回的 json 中获取了 k_BackingField。

我已将 DataContract 和 DataMember 属性添加到 .net c# 对象,但在客户端的 json 上却一无所获。

[XmlRoot("person")]
[Serializable]
public class LinkedIn

    [XmlElement("id")]
    public string ID  get; set; 

    [XmlElement("industry")]
    public string Industry  get; set; 

    [XmlElement("first-name")]
    public string FirstName  get; set; 

    [XmlElement("last-name")]
    public string LastName  get; set; 
    [XmlElement("headline")]

返回的json示例:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"

【问题讨论】:

【参考方案1】:

在我的情况下,这个错误是针对 Newtonsoft.Json 版本的,服务器寻找 6.0.0 版本,我有 11.0,所以我必须安装 6.0.0 版本

【讨论】:

【参考方案2】:

默认的 WebApi 序列化程序会将“__BackingField:”语法添加到 c# 自动属性中。将此添加到 App_Start 中的 WebConfig 以获得您可能正在寻找的更清晰的 json。

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

【讨论】:

这解决了问题。我认为汽车属性很干净。到处使用支持字段似乎很愚蠢。并引入了很多混乱,有时甚至是混乱。 这对我有用。在我的例子中,我有一个已经被 WCF 和 ASMX webservices 使用的现有类,所以我不能只为我的新 WebAPI 项目更改它。 问题是为什么WebApi序列化器会默认添加“__BackingField:”? 很好的解决方案。就我而言,我需要使用 [Serializable] 保存到内存缓存中。可序列化是必需的。 没有 *** 我该怎么办?谢谢。【参考方案3】:

我必须使用 [Serializable] 属性,因此无法删除它。

XmlSerializer ignores [XmlAttribute] in WebApi

上述解决方案为我解决了。

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;

【讨论】:

【参考方案4】:

当我的类中有自引用属性时,我遇到了这个问题,例如:

class Person 
 List<Person> Friends  get; set;

结果,这个人和自己成了朋友。我只是确保我的结果集中没有自引用对象。希望这会有所帮助。

【讨论】:

【参考方案5】:

几个选项:

    从模型中删除 [Serializable]

    [DataContract][DataMember][Serializable] 一起添加到您的模型中

    以下行添加到App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

【讨论】:

【参考方案6】:

在 JSON.NET 的情况下可能会有所帮助的另一种解决方案。使用 [Newtonsoft.Json.JsonObject] 属性标记类可能就足够了。

我正在使用从 xsd 构建的 cs 类,并正在使用部分类添加一些属性。在 json 序列化之后,这些属性被标记为 k_BackingField。其他答案中提到的 JsonFormatter 设置也有帮助,但更简单的是用 [JsonObject] 属性标记部分类。

【讨论】:

【参考方案7】:

我们有一些标记为[Serializable] 的对象,因此它们可以使用传统方法进行序列化,但我们需要在 JSON 中干净地序列化它们以用于 Web API。将 IgnoreSerializableAttribute 设置为 true 将阻止 Newtonsoft.Json 表现得像 Microsoft 的序列化程序,而只会序列化公共属性。

TLDR:将此添加到 WebApiConfig.cs:

((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

主持人:与其删除一个已经被问过多次的问题的真正好答案,不如删除重复的问题。这是对有效问题的有效答案。

【讨论】:

这应该是正确的答案。删除序列化或使用 datacontract 和 datamember 属性并不总是正确的解决方案。 我们中的许多人,包括 OP,都没有使用 Webapi 或 MVVM 或者你们在做什么。当我有一个带有 service.svc 的普通soap WCF 服务时,app_start 和 webapiconfig 是什么? 谢谢,这个解决方案对我有用。它从 WEB API 响应中删除 k__BackingField。【参考方案8】:

朋友,不要这样声明属性:

public String DiscretionCode  get; set; 
public String DiscretionDescription  get; set; 

但是,创建辅助变量,就像旧的......

private String discretionCode;

public String DiscretionCode 
 
    get  return discretionCode;
    set  discretionCode = value; 

【讨论】:

为什么?你能给出一个共鸣吗? @Lucenty 它给出了这样的 JSON.. [ "discreationCode" : "x"],在序列化时。 但这正是我所期望的——这就是 JSON 序列化数据的方式。而且我认为带有辅助变量的代码会给出相同的结果。 k_BackingField 已添加以指示自动属性已被序列化。如果您将自动属性重构为属性和支持字段,那么问题就会消失。我认为这个线程中有更好的解决方案,但这很有效。【参考方案9】:

简单而体面的数据公开方式 我们需要将对象中的数据公开为易于阅读且一致的格式

先删除[Serializable]

    [Serializable]

现在在类中添加 [DataContract] 并为属性添加 [DataMember],如下例所示

[DataContract]
public class UserDiscretion : UserReport

    [DataMember]
    public String DiscretionCode  get; set; 
    public String DiscretionDescription  get; set; 

希望对您有所帮助 谢谢。

【讨论】:

如果使用Web API,根本不需要添加DataContract和DataMember属性——只需返回对象,它就会自动序列化。 如果有人从头开始开发,那么使用提供对象返回类型的 Web API 将非常棒,不需要任何类型的类型转换来向客户端公开。但是对于@AlumCloud.com 的问题,如果他在现有的应用程序中,那么他的问题的解决方案将是首先删除 [Serializable],然后在类中添加 [DataContract],并按照建议为属性添加 [DataMember],如下所示 这会给您的课程增加大量的“噪音”,而且基本上是不必要的(请参阅所有其他 cmets)。但是,如果您觉得需要实际执行此操作,我建议您使用 PostSharp 之类的工具在编译期间为您添加代码,以免所有这些属性使您的类变得混乱。【参考方案10】:

从你的班级中删除 [Serializable]

【讨论】:

现在我想知道为什么我认为我首先需要 [Serializable]。我的 Xml 序列化在没有它的情况下工作,而 JSON 在没有它的情况下工作。 这不适用于 WCF 服务。使用 RESTful 服务返回有效负载时,如果您删除 [Serializable],则不会产生任何数据。添加 System.Runtime.Serialization 并使用 [DataContract] 作为类,使用 [DataMember] 作为属性。 这个答案和伊恩评论似乎涵盖了这两种情况。 WCF 还是 WCF,这是个问题。 @Rhyous - 在 Web API 中你不需要 [Serializable],因为 Web API 的设置假设你将序列化并返回你的对象(因为这基本上是整个想法) - 在其他 C# 应用程序中,您通常需要 Serializable 来区分可序列化对象 您好,它有效,但我需要将 [Serializable] 保留到我的班级,因为我的后台使用了相同的班级并且我使用了 SQL 服务器会话。要将此类存储在会话中,我需要保留 [Serializable]。请问还有其他解决方案吗?【参考方案11】:

我将DataContractJsonSerializer 与来自另一个程序集的具有Serializable 属性的类一起使用。输出包含“k__BackingField”。删除 Serializable 属性(在另一个程序集中)修复了这个问题。不知道为什么。

【讨论】:

【参考方案12】:

假设您在 MVC 项目中看到此问题,我发现替换 @html.JsonData 的使用非常简单。这是过去对我有用的 sn-p 代码:

<input type="hidden" id="Model" value="@Html.Raw(new System.Web.Script.Serialization.javascriptSerializer().Serialize(Model))" />

没有那么优雅,但很简单。

【讨论】:

【参考方案13】:

如果类可以用于序列化,实际上不推荐使用自动属性语法。原因是支持字段是由编译器生成的,每次编译代码时可能会有所不同。即使没有对类进行任何更改(只是重新编译代码),这也可能导致不兼容问题。

我认为应用 DataMember 属性将解决这种情况下的问题。但如果需要在序列化中使用该类,我建议使用完整的属性语法。

【讨论】:

大声笑,实现了长版本并将私有字段设置为client.home:对象_fName:“Storefront”_headline:“StorefrontDoors.NET的CEO”_id:“”_industry:“” 将该数据合同添加到类的顶部,并将数据成员添加到我感兴趣的每个属性中。 @AlumCloud.Com +1 [DataContract] 和 [DataMember]。不要忘记添加:System.Runtime.Serialization

以上是关于反序列化时如何从json中删除k__BackingField的主要内容,如果未能解决你的问题,请参考以下文章

使用已知和未知字段反序列化 json

如何反序列化json空数组

如何在 C# 中使用 JSON 反序列化 oData V2?

使用 C# 反序列化复杂的嵌套 JSON

Python —— Json序列号与反序列化

Newtonsoft.Json 序列 反序列 IEnumerable