SerializationException使用DataContractSerializer序列化newtonsoft jobject

时间:2013-04-17 20:51:42

标签: .net wcf json.net datacontractserializer netnamedpipebinding

更新 - 我遇到的问题是用户错误。请参阅下面的答案。

我有一个类,我想添加到WCF API的DataContract,它应该是“绑定不可知”;即,它应该能够支持多个绑定,包括BasicHttp和NamedPipe。我要添加到数据协定的类使用Newtonsoft.Json.Linq.JObject来存储成员数据:

[DataContract]
public class MyFacet
{
    public MyFacet(string facetName)
    {
        Initialize();
        FacetName = facetName;
    }

    internal JObject JsonObject { get; private set; }

    [OnDeserializing]  // required for deserialization to init JsonObject
    private void OnDeserializing(StreamingContext c)
    {
        Initialize();
    }

    private void Initialize()
    {
        JsonObject = new JObject();
    }
    [DataMember]
    public string FacetName
    {
        get
        {
            return GetProperty<string>("facet");
        }
        private set
        {
            SetProperty("facet", value);
        }
    }

    public string ToJson()
    {
        return JsonObject.ToString(Newtonsoft.Json.Formatting.None);
    }

    public T GetProperty<T>(string key)
    {
        JToken value;
        if (JsonObject.TryGetValue(key, out value))
        {
            return value.Value<T>();
        }
        return default(T);
    }

    public void SetProperty(string name, object value)
    {
        SetProperty(name, new JValue(value));
    }

    internal void SetProperty(string name, JToken value)
    {
        JsonObject[name] = value;
    }
}

由于种种原因,我希望保留这个课程,如果可能的话。当我尝试使用DataContractSerializer(在测试应用程序中)序列化此类时,我收到以下错误:

System.Runtime.Serialization.SerializationException: 
Type 'ConsoleTest.MyFacet' with data contract name 
'MyFacet:http://schemas.datacontract.org/2004/07/ConsoleTest' is not expected.
Consider using a DataContractResolver or add any types not known statically to 
the list of known types - for example, by using the KnownTypeAttribute attribute 
or by adding them to the list of known types passed to DataContractSerializer.

基本上,这对我有意义。但是,将各种Newtonsoft类型添加为KnownTypes不起作用 - 这会导致“递归收集数据协定”错误。如果我尝试实现DataContractResolver,我想我会遇到同样的问题。

我相信我可以使用Newtonsoft序列化程序将JObject序列化为XML。看起来我有几个选择:

  • 使用IDataContractSurrogate并提供JObject的反序列化代理
  • 使用IClientMessageFormatter创建自定义序列化/反序列化
  • 以其他方式配置/覆盖de / serialization'系统'以使用Newtonsoft序列化程序代替或与DataContractSerializer一起使用。

而且,我担心必须支持各种绑定。命名管道使用二进制编码,我不确定这会如何影响这个序列化问题 - 也许这意味着我必须使用代理?

2 个答案:

答案 0 :(得分:0)

我认为,KnownType 不会提供帮助 - 因为它只会帮助“找到”类型,而wcf DataContractSerializer应该知道如何序列化。

但事实并非如此,因为JObject不包含DataContractDataMember属性。

如果JObject是xml可序列化的,我会考虑使用xml序列化而不是DataContract序列化。

答案 1 :(得分:0)

原来这是%100用户错误。在我的序列化测试工具中,我在创建DataContractSerializer时传递了错误的类型。以下演示了错误:

Console.WriteLine("serializing...");
MyFacet facet = new MyFacet("MyFacet");
// On the following line, I was passing the wrong type to the ctor.
// Needed to pass "MyFacet" here, not "Person"
//!ERROR
DataContractSerializer serializer = new DataContractSerializer(typeof(Person));//!ERROR
var settings = new XmlWriterSettings { Indent = true };
using (var writer = XmlWriter.Create(fileName, settings))
    serializer.WriteObject(writer, facet);

一旦我修正了错误,原始帖子中的类序列化就好了。我最初得到的错误消息真的让我失望了。我假设有一些关于JObject或其中一个导致问题的Newtonsoft类型,事实上,我显然甚至没有尝试序列化任何这些类型。