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

119

我将一个XML文件序列化为.NET C#对象后,返回的JSON中出现了k_BackingField。

我已经给.NET C#对象添加了DataContract和DataMember属性,但客户端在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"
13个回答

118

从您的类中删除 [Serializable]


4
现在我在想,为什么我一开始认为需要 [Serializable]。我的 Xml 序列化和 JSON 序列化可以在没有它的情况下正常工作。 - Rhyous
14
这在WCF服务中不能使用。当使用RESTful服务返回有效负载时,如果删除[Serializable],将没有任何数据输出。需要添加System.Runtime.Serialization,对于类需要使用[DataContract],对于属性需要使用[DataMember]。 - Ian Newland
这个回答和Ian的评论似乎都涵盖了两种情况。使用WCF还是不使用WCF,这是一个问题。 - granadaCoder
1
@Rhyous - 在Web API中,您不需要[Serializable],因为Web API的设置是基于您将序列化并返回对象的假设(因为这基本上是整个想法)- 在其他C#应用程序中,通常需要Serializable来区分可序列化的对象。 - Jon Story
1
你好,它可以工作,但我需要在我的类中保留[Serializable],因为我已经将同一类用于我的后台,并且我已经使用了SQL Server会话。为了将此类存储在会话中,我需要保留[Serializable]。还有其他解决方案吗? - Abhijit Pandya
显示剩余2条评论

66

默认的WebApi序列化器会在C#自动属性中添加"__BackingField:"语法。在App_Start的WebConfig中添加此内容,以获得更干净、更易读的JSON。

默认的WebApi序列化器会在C#自动属性中添加"__BackingField:"语法。在App_Start的WebConfig中添加此内容,以获得更干净、更易读的JSON。

using Newtonsoft.Json;
...

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

5
这解决了问题。我认为自动属性更加简洁。在所有地方使用后备字段似乎很愚蠢,会引入许多混乱和不必要的复杂度。 - Romesh D. Niriella
1
这对我很有效。在我的情况下,我有一个已经被 WCF 和 ASMX Web 服务使用的现有类,所以我不能只是为我的新 WebAPI 项目改变它。 - samiup
8
为什么WebApi序列化器默认会添加"__BackingField:"这个东西呢? - Teoman shipahi
3
没有 StackOverflow,我该怎么办?谢谢。 - camainc
在WCF端的哪里添加这段代码? - undefined
显示剩余2条评论

47
自动属性语法在可序列化的类中并不推荐使用,原因是由编译器生成的后备字段每次编译代码时都可能不同。即使没有更改类(只是重新编译代码),这也可能导致兼容性问题。我认为在这种情况下应用DataMember属性将解决该问题。但如果该类需要用于序列化,则建议使用完整的属性语法。

实现了长版本,它将私有字段设置为client.home: Object _fName: "Storefront" _headline: "StorefrontDoors.NET的CEO" _id: "" _industry: "" - Filling The Stack is What I DO
21
将datacontract添加到类的顶部,并将datamember添加到我感兴趣的每个属性上,这样做起作用了。 - Filling The Stack is What I DO
3
@AlumCloud.Com +1 对于 [DataContract] 和 [DataMember]。别忘了添加:System.Runtime.Serialization - Ian Newland

39

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

TLDR: 将以下内容添加到 WebApiConfig.cs 中:

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

版主:与其删除一个已经被多次提出的问题的一个非常好的答案,不如删除重复的问题。这是对一个合法问题的合法回答。


4
这应该是正确的答案。去除序列化或使用datacontract和datamember属性并非始终是正确的解决方案。 - Houssam Hamdan
我们中的许多人,包括OP在内,没有使用Webapi或MVVM或者你们正在谈论的任何其他技术。当我有一个普通的soap WCF服务,其中包含service.svc时,app_start和webapiconfig是什么? - Christian
谢谢,这个解决方案对我有效。它从WEB API响应中删除了k__BackingField。 - Vijay Chauhan

14

简单易懂又体面的数据暴露方式 我们需要以易读且一致的格式将对象中的数据暴露出来。


首先移除[Serializable]

    [Serializable]

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

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

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

希望这能帮到您
谢谢。


1
如果使用Web API,根本不需要添加DataContract和DataMember属性,只需返回对象即可自动序列化。 - Jon Story
如果有人从零开始开发,那么使用Web API将是一个很好的选择,它提供了对象返回类型,不需要任何类型转换来暴露给客户端。 但是对于@AlumCloud.com的问题,如果他在现有应用程序中,那么解决他的问题的方法是 首先删除[Serializable] 然后在类中添加[DataContract],并为属性添加[DataMember],如下所建议。 - Nagendra Upwanshi
1
这会给你的类添加大量的“噪音”,而且基本上是不必要的(请参见其他所有评论)。然而,如果有人真的感觉有必要这样做,我建议在编译期间使用像PostSharp这样的工具来为你添加代码,以便它不会用所有这些属性弄乱你的类。 - camainc

8

有几个选项:

  1. 从模型中删除[Serializable]

  2. 在您的模型中添加[DataContract][DataMember],以及[Serializable]

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

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

4

另一种解决方案是在使用JSON.NET时可能会有所帮助。只需使用[Newtonsoft.Json.JsonObject]属性标记类即可。

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


2

我使用了DataContractJsonSerializer来处理另一个程序集中带有Serializable属性的类。输出结果包含"k__BackingField"。移除(另一个程序集中的)Serializable属性可以解决这个问题。 不确定原因。


0

0

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

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

最终结果是,这个人和他自己是朋友。我只是确保我的结果集中没有自引用的对象。希望这可以帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接