2016-09-08 30 views
2

我有一堆域對象,我序列化,發送到其他應用程序,然後反序列化使用Json.Net。這些對象可具有屬性是動態屬性忽略類型而不修改類?

  • 定義爲抽象基類與多個派生類
  • 動態屬性

我用TypeNameHandling.Auto,它增加了$type屬性,從不同類型的聲明的類型。但是,此設置對我的動態屬性有不良副作用,即它們的類型也會被聲明。

在下面的示例中,model是在我的C#代碼中定義爲public dynamic Model { get; set; }的動態屬性。

"model":{"$type":"<>f__AnonymousType0`3[[System.String, mscorlib],[System.String, mscorlib],[System.String, mscorlib]], ExampleAssembly","link":"http://www.google.com","name":"John"} 

當嘗試反序列化這個字符串在另一個組件,Json.Net不能(當然)找到ExampleAssembly。使用TypeNameHandling.None屬性賦予以下屬性系列化

"model": {"link":"http://www.google.com","name":"John"} 

哪些可以成功反序列化到dynamic。但是,這會打破派生類型的反序列化。

有關如何在不實現自定義IContractResolver及其他自定義代碼的情況下如何使其工作的任何想法?

我沒有自己的領域對象,所以我不能裝飾他們或他們的屬性與屬性或允許他們實現接口等我在找什麼是某種設置在序列化器中省略類型爲dynamics

恕我直言,這應該可以通過設置配置不知何故,我只是沒有找到它。

+0

[JsonIgnore]或有條件序列化(http://www.newtonsoft.com /json/help/html/conditionalproperties.htm)可能會有用 – Nair

+0

@Nair:謝謝,但不幸的不是。我不擁有域對象,不能用屬性或方法修飾。此外,這不能很好地擴展,因爲我必須對所有對象都這樣做。 – pardahlman

+0

將'[JsonProperty(TypeNameHandling = TypeNameHandling.None)]'添加到相關的屬性將是最直接的方式 - 但在您的評論中,你說你不能這樣做。你可能想編輯這個問題來澄清這個要求。 – dbc

回答

2

Json.Net沒有提供特定的設置來關閉僅用於動態類型的類型名稱處理。如果你不能(或者不想)用[JsonProperty(TypeNameHandling = TypeNameHandling.None)]來標記相關的動態屬性,那麼你唯一的選擇(即修改Json.Net源代碼本身)就是實現一個自定義合約解析器來以編程方式應用行爲。但是不要擔心,如果您從Json.Net提供的解析器之一(例如DefaultContractResolverCamelCasePropertyNamesContractResolver)派生解析器,這並不難。

這裏是所有你需要的代碼:

using System; 
using System.Reflection; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 

public class OmitTypeNamesOnDynamicsResolver : DefaultContractResolver 
{ 
    public static readonly OmitTypeNamesOnDynamicsResolver Instance = new OmitTypeNamesOnDynamicsResolver(); 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty prop = base.CreateProperty(member, memberSerialization); 
     if (member.GetCustomAttribute<System.Runtime.CompilerServices.DynamicAttribute>() != null) 
     { 
      prop.TypeNameHandling = TypeNameHandling.None; 
     } 
     return prop; 
    } 
} 

然後,只需解析器添加到JsonSerializerSettings,你應該準備就緒。

JsonSerializerSettings settings = new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.Auto, 
    ContractResolver = OmitTypeNamesOnDynamicsResolver.Instance 
}; 

string json = JsonConvert.SerializeObject(foo, settings); 

這裏是一個往返演示證明概念:

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     Foo foo = new Foo 
     { 
      Model = new { link = "http://www.google.com", name = "John" }, 
      Widget1 = new Doodad { Name = "Sprocket", Size = 10 }, 
      Widget2 = new Thingy { Name = "Coil", Strength = 5 } 
     }; 

     JsonSerializerSettings settings = new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.Auto, 
      ContractResolver = OmitTypeNamesOnDynamicsResolver.Instance, 
      Formatting = Formatting.Indented 
     }; 

     string json = JsonConvert.SerializeObject(foo, settings); 
     Console.WriteLine(json); 
     Console.WriteLine(); 

     Foo foo2 = JsonConvert.DeserializeObject<Foo>(json, settings); 
     Console.WriteLine(foo2.Model.link); 
     Console.WriteLine(foo2.Model.name); 
     Console.WriteLine(foo2.Widget1.Name + " (" + foo2.Widget1.GetType().Name + ")"); 
     Console.WriteLine(foo2.Widget2.Name + " (" + foo2.Widget2.GetType().Name + ")"); 
    } 
} 

public class Foo 
{ 
    public dynamic Model { get; set; } 
    public AbstractWidget Widget1 { get; set; } 
    public AbstractWidget Widget2 { get; set; } 
} 

public class AbstractWidget 
{ 
    public string Name { get; set; } 
} 

public class Thingy : AbstractWidget 
{ 
    public int Strength { get; set; } 
} 

public class Doodad : AbstractWidget 
{ 
    public int Size { get; set; } 
} 

輸出:

{ 
    "Model": { 
    "link": "http://www.google.com", 
    "name": "John" 
    }, 
    "Widget1": { 
    "$type": "Doodad, JsonTest", 
    "Size": 10, 
    "Name": "Sprocket" 
    }, 
    "Widget2": { 
    "$type": "Thingy, JsonTest", 
    "Strength": 5, 
    "Name": "Coil" 
    } 
} 

http://www.google.com 
John 
Sprocket (Doodad) 
Coil (Thingy) 
+0

美麗!正如我所說,我寧願有一些沒有自定義類的開箱即用功能。但是,您的聯繫人解析器的實現是非常小的,這是值得讚賞的。感謝您的書面回覆! – pardahlman

+0

沒問題;很高興我能幫上忙。 –

相關問題