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


104

将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"

Answers:


45

如果可以在序列化中使用该类,则实际上不建议使用自动属性语法。原因是后备字段是由编译器生成的,每次编译代码时都会不同。即使未对类进行任何更改,这也可能导致不兼容问题(只需重新编译代码)。

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


大声笑,实现了长版本,并设定私有字段的client.home:对象_fName:“店面” _headline:“CEO在StorefrontDoors.NET” _id:“” _industry:“”
灌装堆栈是我做的

21
将数据合同添加到类的顶部,并将数据成员添加到我感兴趣的每个属性中。
填满堆栈就是我要做的事情

3
@ AlumCloud.Com为[DataContract]和[DataMember] +1。不要忘记添加:System.Runtime.Serialization
伊恩·纽兰德

109

[Serializable]从班级中删除


2
现在我想知道为什么我以为我首先需要[可序列化]。我的Xml序列化在没有它的情况下工作,而JSON在没有它的情况下工作。
Rhyous 2015年

11
这不适用于WCF服务。使用RESTful服务返回有效负载时,如果删除[Serializable],则不会产生任何数据。添加System.Runtime.Serialization并将[DataContract]用于类,将[DataMember]用于属性。
伊恩·纽兰德

这个答案和伊恩的评论似乎涵盖了两种情况。对于WCF还是不对WCF,这就是问题。
granadaCoder 2015年

1
@Rhyous-在Web API中,您不需要[可序列化],因为Web API的设置是假设您将序列化并返回对象(因为这基本上是整个想法)-在其他C#应用程序中,通常需要Serializable来区分可序列化的对象
Jon Story

谢谢,我一直坚持使用[Serializable],因此添加后备字段会有所帮助。
ohmusama

59

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

using Newtonsoft.Json;
...

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

3
这解决了问题。我认为汽车属性很干净。在任何地方使用后备字段似乎都是愚蠢的。并带来很多混乱甚至混乱的情况。
罗密什·D·尼里埃拉

这对我有用。就我而言,我有一个已经由WCF和ASMX Web服务使用的现有类,因此我不能只为我的新WebAPI项目更改它。
samiup

4
问题是为什么地球上WebApi序列化程序默认会添加“ __BackingField:”?
Teoman shipahi

好的解决方案。就我而言,我需要使用[Serializable]保存到内存缓存中。可序列化是必需的。
平阮光

2
没有StackOverflow怎么办?谢谢。
camainc

35

我们将一些对象标记为,[Serializable]以便可以使用传统方法对其进行序列化,但是我们需要使用JSON对其进行干净地序列化才能与Web API一起使用。设置IgnoreSerializableAttributetrue将会阻止Newtonsoft.Json像Microsoft的序列化器那样运行,而只会序列化公共属性。

TLDR:将此添加到WebApiConfig.cs:

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

主持人:请删除重复的问题,而不是删除对已经问过几次的问题的一个很好的答案。这是对有效问题的有效答案。


3
这应该是正确的答案。删除序列化或使用datacontract和datamember属性并不总是正确的解决方案。
侯萨姆·哈姆丹

我们中的许多人(包括OP)并未使用Webapi或MVVM,或者你们正在使用的是什么。当我使用service.svc获得普通的肥皂WCF服务时,app_start和webapiconfig是什么?
克里斯蒂安

10

简单易行的方式公开数据 简单易行的我们需要以易于阅读和一致的格式公开对象中的数据


首先删除[可序列化]

    [Serializable]

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

[DataContract]
public class UserDiscretion : UserReport
{
    [DataMember]
    public String DiscretionCode { get; set; }
    public String DiscretionDescription { get; set; }
}

希望对
您有所帮助 谢谢。


1
如果使用Web API,则根本不需要添加DataContract和DataMember属性-只需返回该对象,它将自动进行序列化。
乔恩·斯托利

如果有人从头开始开发,那么最好使用Web API,它将提供Object返回类型,而无需将任何类型转换都公开给客户端。但是对于@ AlumCloud.com问题,如果他在现有应用程序中,那么解决该问题的方法是:首先删除[Serializable],然后在类中添加[DataContract],并为以下属性添加[DataMember],如下所示
Nagendra Upwanshi

1
这会给您的类增加大量的“噪音”,并且基本上是不必要的(请参阅所有其他注释)。但是,如果觉得确实需要这样做,我建议您使用PostSharp之类的东西在编译过程中为您添加代码,以免使用所有这些属性使您的类混乱。
camainc

7

几个选项:

  1. [Serializable]从模型中删除

  2. [DataContract]和添加[DataMember]到模型中 [Serializable]

  3. 将以下行添加到 App_Start/WebApiConfig.cs

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

3

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

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


2

我正在使用DataContractJsonSerializer另一个具有该Serializable属性的程序集中的类。输出包含“ k__BackingField”。除去该Serializable属性(在另一个程序集中)可解决此问题。不知道为什么。


0

假设您在MVC项目中看到此问题,我发现替换@ Html.JsonData的使用非常简单。这是过去为我工作的一小段代码:

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

不那么优雅,但紧要关头。


0

当我在类中具有自引用属性时,我遇到了这个问题;

class Person {
 List<Person> Friends { get; set;}
}

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




-2

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

public String DiscretionCode { get; set; }
public String DiscretionDescription { get; set; }

但是,请像以前一样创建辅助变量。

private String discretionCode;

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

1
为什么?你能引起共鸣吗?
Lucenty

@Lucenty在序列化时会给出这样的JSON。[{[“ discreationCode”:“ x”}]。
Ammar Ameerdeen

但这就是我所期望的-这就是JSON序列化数据的方式。而且我认为带有辅助vars的代码将产生相同的结果。
Lucenty

添加了k_BackingField来指示已对自动属性进行了序列化。如果将自动属性重构为属性和后备字段,则问题将消失。我认为在此线程中有更好的解决方案,但这可行。
timB33 '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.