我遇到了一个问题,即Web客户端应用程序无法正确反序列化JSON消息。当表示消息的类型标记为[Serializable]时,会导致该错误。
下面是一些可以重现问题的代码。它需要Newtonsoft.Json和Microsoft.AspNet.WebApi.Client NuGet包。
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Text;
namespace ConsoleApplication7
{
internal class Program
{
private static void Main()
{
String cargo = "Hello";
SerializableType serializableTypeOriginal = new SerializableType(cargo);
String jsonFromSerializableType = JsonConvert.SerializeObject(serializableTypeOriginal);
NonSerializableType nonSerializableTypeOriginalNonSerializableType = new NonSerializableType(cargo);
String jsonFromNonSerializableType = JsonConvert.SerializeObject(nonSerializableTypeOriginalNonSerializableType);
System.Diagnostics.Debug.Assert(jsonFromSerializableType == jsonFromNonSerializableType);
HttpContent httpContent = new StringContent(jsonFromSerializableType, new UTF8Encoding(), "application/json");
SerializableType serializableTypeFromSerializableType = httpContent.ReadAsAsync<SerializableType>().Result;
//serializableTypeFromSerializableType.A == null ✘
httpContent = new StringContent(jsonFromSerializableType, new UTF8Encoding(), "application/json");
NonSerializableType nonSerializableTypeFromSerializableType = httpContent.ReadAsAsync<NonSerializableType>().Result;
//nonSerializableTypeFromSerializableType.A == "Hello" ✔
httpContent = new StringContent(jsonFromNonSerializableType, new UTF8Encoding(), "application/json");
SerializableType serializableTypeFromNonSerializableType = httpContent.ReadAsAsync<SerializableType>().Result;
//serializableTypeFromNonSerializableType.A == null ✘
httpContent = new StringContent(jsonFromNonSerializableType, new UTF8Encoding(), "application/json");
NonSerializableType nonSerializableTypeFromNonSerializableType = httpContent.ReadAsAsync<NonSerializableType>().Result;
//nonSerializableTypeFromNonSerializableType.A == "Hello" ✔
}
}
[Serializable]
public class SerializableType
{
private readonly string _a;
public SerializableType(String a)
{
_a = a;
}
public string A
{
get { return _a; }
}
public override string ToString()
{
return string.Format("A: {0}", A);
}
}
public class NonSerializableType
{
private readonly string _a;
public NonSerializableType(String a)
{
_a = a;
}
public string A
{
get { return _a; }
}
public override string ToString()
{
return string.Format("A: {0}", A);
}
}
}
这是NuGet包文件:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.1.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
</packages>
在我看来,对于没有使用[Serializable]属性修饰的类,JSON.Net将使用构造函数注入来在反序列化时对类进行水合。但是当[序列化]属性存在时,我无法解决该怎么做?
我可以使用[Serialization]属性,并使JSON.Net使用构造函数吗?
答案 0 :(得分:1)
我制定了一个解决方案:
ReadAsAsync(http://msdn.microsoft.com/en-us/library/hh943959(v=vs.118).aspx)的覆盖允许您指定要明确使用的MediaTypeFormatter。
您可以通过更改&#34; DefaultContractResolver&#34;上的属性IgnoreSerializationAttribute来指示JsonMediaTypeFormatter忽略[Serializable]属性。 (http://james.newtonking.com/json/help/index.html?topic=html/SerializationAttributes.htm)。
把各个部分放在一起:
private static void Main()
{
JsonMediaTypeFormatter mediaTypeFormatter = new JsonMediaTypeFormatter();
mediaTypeFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver()
{
IgnoreSerializableAttribute = true
};
String cargo = "Hello";
SerializableType serializableTypeOriginal = new SerializableType(cargo);
String jsonFromSerializableType = JsonConvert.SerializeObject(serializableTypeOriginal);
NonSerializableType nonSerializableTypeOriginalNonSerializableType = new NonSerializableType(cargo);
String jsonFromNonSerializableType = JsonConvert.SerializeObject(nonSerializableTypeOriginalNonSerializableType);
System.Diagnostics.Debug.Assert(jsonFromSerializableType == jsonFromNonSerializableType);
HttpContent httpContent = new StringContent(jsonFromSerializableType, new UTF8Encoding(), "application/json");
SerializableType serializableTypeFromSerializableType = httpContent.ReadAsAsync<SerializableType>(new[] { mediaTypeFormatter }).Result;
//serializableTypeFromSerializableType.A == "Hello" ✔
httpContent = new StringContent(jsonFromSerializableType, new UTF8Encoding(), "application/json");
NonSerializableType nonSerializableTypeFromSerializableType = httpContent.ReadAsAsync<NonSerializableType>(new[] { mediaTypeFormatter }).Result;
//nonSerializableTypeFromSerializableType.A == "Hello" ✔
httpContent = new StringContent(jsonFromNonSerializableType, new UTF8Encoding(), "application/json");
SerializableType serializableTypeFromNonSerializableType = httpContent.ReadAsAsync<SerializableType>(new[] { mediaTypeFormatter }).Result;
//serializableTypeFromNonSerializableType.A == "Hello" ✔
httpContent = new StringContent(jsonFromNonSerializableType, new UTF8Encoding(), "application/json");
NonSerializableType nonSerializableTypeFromNonSerializableType = httpContent.ReadAsAsync<NonSerializableType>(new[] { mediaTypeFormatter }).Result;
//nonSerializableTypeFromNonSerializableType.A == "Hello" ✔
}
答案 1 :(得分:1)
如果您控制标记为[Serializable]
的类型的源代码,则另一种解决方案是向该类添加[JsonObject]
属性:
[Serializable]
[JsonObject]
public class SerializableType
{
...
}
然后从原始问题重新运行测试,你应该得到所有四个的“Hello”。