我需要做什么才能使Json.Net表现得好像[Serializable]属性不存在?

时间:2014-03-20 06:46:33

标签: c# asp.net-web-api json.net

我遇到了一个问题,即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使用构造函数吗?

2 个答案:

答案 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”。