0

更新 - 我在這裏遇到的問題是用戶錯誤。請參閱下面的答案。SerializationException使用DataContractSerializer序列化newtonsoft jobject

我有一個類,我想添加到一個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的反序列化的替代創建自定義序列化/反序列化
  • 不知怎的,其他配置/覆蓋德/序列化「制度'使用Newtonsoft序列化程序代替DataContractSerializer或與之一起使用。

而且,我擔心不得不支持各種綁定。命名管道使用二進制編碼,我不知道這是如何影響這個序列化問題 - 也許這意味着我必須使用代理?

+0

從錯誤消息 - 你看看[通用數據合同解析器](http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver的.aspx)? –

+0

我認爲DataContractResolver會做類似於添加KnownTypeAttributes的事情,只會嘗試在運行時進行。就我而言,我相信DataContractSerializer根本不能反序列化類型(例如JObject),即使它知道它們是什麼。 –

回答

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類型之一,事實上,我顯然甚至沒有試圖序列化任何這些類型。

0

我認爲,KnownType不會幫助 - 因爲它應該只是幫助「查找」的類型,WCF DataContractSerializer時應該知道如何序列化。

它並沒有,因爲JObject不包括DataContractDataMember屬性。

如果JObject是xml可序列化的,我會考慮使用xml序列化來代替DataContract序列化。

相關問題