关于c#:我该怎么做才能使Json.Net表现得好像[Serializable]属性不存在?

What do I need to do so that Json.Net to behaves as if the [Serializable] attribute isn't there?

我有一个问题,其中Web客户端应用程序无法正确反序列化JSON消息。 该错误是由于代表消息的类型被标记为[可序列化]而引起的。

下面是一些代码,重现该问题。 它需要Newtonsoft.Json和Microsoft.AspNet.WebApi.Client NuGet程序包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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软件包文件:

1
2
3
4
5
<?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]属性存在时,我无法解决该怎么办?

我可以具有[Serialization]属性,并使JSON.Net使用构造函数吗?


如果您控制标记为[Serializable]的类型的源代码,则另一种解决方案是将[JsonObject]属性添加到该类:

1
2
3
4
5
6
    [Serializable]
    [JsonObject]
    public class SerializableType
    {
        ...
    }

然后从原始问题重新运行测试,您将为所有四个问题打" Hello"。


我制定了一个解决方案:

ReadAsAsync(http://msdn.microsoft.com/zh-cn/library/hh943959(v=vs.118).aspx)有一个替代,它允许您指定要显式使用的MediaTypeFormatter。

您可以通过更改" DefaultContractResolver"(http://james.newtonking.com/json/help/index.html?topic=html/SerializationAttributes.htm)上的属性IgnoreSerializationAttribute来指示JsonMediaTypeFormatter忽略[Serializable]属性。 。

将各个部分放在一起:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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" ?

    }