使JSON.NET和Serializable属性协同工作

时间:2014-01-03 22:44:34

标签: asp.net-mvc json serialization asp.net-web-api json.net

我正在使用JSON.NET,并且在WEBAPI对象反序列化过程中遇到了一些麻烦。经过一些研究后,我发现该课程标有[Serializable]。当我删除它时,反序列化就好了。

有关这方面的更多详细信息,请访问:

Why won't Web API deserialize this but JSON.Net will?

现在谈到我使用binaryformatter创建从此对象类计算的哈希值的问题。 但Binaryformatter要求必须将类标记为[Serializable]。

你能否建议我采用任何方法让两件事同时发挥作用?

3 个答案:

答案 0 :(得分:24)

找到解决方案:

首先,检查您的Newtonsoft.JSON版本是否大于4.5或只是使用NuGET进行更新

根据版本说明,两者都可以使用一些额外的注释从这个版本开始协同工作。

http://james.newtonking.com/archive/2012/04/11/json-net-4-5-release-2-serializable-support-and-bug-fixes

“现在,如果您正在序列化具有该属性但不想要新行为的类型,则可以使用JsonObjectAttribute在类型上覆盖它”

[JsonObject]
[Serializable]
public class Foobar {

现在可以使用JSON.NET,在我的例子中,可以使用带有[Serializable]属性的binaryformatter。

答案 1 :(得分:5)

在每个类上指定JsonObject的替代方法是告诉web.api全局忽略Serialize属性。这可以通过重置web api JsonFormatter上的DefaultContractResolver来完成:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();

(使用NewtonSoft.Json.Serialization,其中config是System.Web.Http.HttpConfiguration)

从NewtonSoft v4.5开始,DefaultContractResolver上的IgnoreSerializableAttribute属性设置为true,但默认情况下,围绕DefaultContractResolver的web api包装器将此设置为false。

答案 2 :(得分:0)

我正在使用具有Seri​​alizable属性的POCO。在第一种情况下,使用以下方法将请求发布到WebApi可以起作用:

JsonMediaTypeFormatter f = new JsonMediaTypeFormatter()
{
    SerializerSettings = new JsonSerializerSettings()
    {
        ContractResolver = new DefaultContractResolver()
        {
            IgnoreSerializableAttribute = true
        }
    }
};

var result = client.PostAsJsonAsync<IEnumerable<Company>>("company/savecompanies", companies).Result;

//I have truncated the below class for demo purpose
[Serializable]
public class Company
{
    public string CompanyName {get;set;}
}

但是,当我尝试读取WebApi的响应时(该对象以JSON回发),该对象未正确反序列化。没有错误,但是属性值为null。以下代码不起作用:

var readObject = result.Content.ReadAsAsync<IEnumerable<Company>>().Result;

我阅读了Newtonsoft.Json网站https://www.newtonsoft.com/json/help/html/SerializationAttributes.htm上给出的文档,发现了以下内容,并引用了该网站的内容:

Json.NET属性优先于标准.NET序列化 属性(例如,是否同时具有JsonPropertyAttribute和DataMemberAttribute 存在于一个属性上,并且都自定义名称,该名称来自 将使用JsonPropertyAttribute)。

因此,很清楚在标准.NET属性之前是否存在Newtonsoft.Json属性,它们将具有优先权。因此,我可以将同一类用于两个目的。一,当我想发布到WebApi时,Newtonsoft Json序列化器将启动;二,当我想使用BinaryFormatter.Serialize()方法std .NET Serializable属性时,将起作用。

@Javier给出的答案也证实了这一点。 所以我将公司类别修改为:

[JsonObject]
[Serializable]
public class Company
{
    public string CompanyName {get;set;}
}

我能够将相同的类用于这两个目的。而且不需要以下代码:

JsonMediaTypeFormatter f = new JsonMediaTypeFormatter()
{
    SerializerSettings = new JsonSerializerSettings()
    {
        ContractResolver = new DefaultContractResolver()
        {
            IgnoreSerializableAttribute = true
        }
    }
};