2015-09-25 57 views
3

在我當前的項目中,當嘗試轉換Item或其任何子類如ArmorItem時,我遇到了以無限循環結束的問題。
要檢測哪種類型的Item我必須反序列化,我使用了一個名爲ItemConverter的定製JsonConverter使用自定義JsonConverter時的無限轉換循環

Item.cs:

[JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(ItemConverter))] 
public class Item 
{ 
    [JsonProperty("id")] public int Id { get; } 
    [JsonProperty("type")] public string ItemType { get; } 

    [JsonConstructor] 
    public Item(int id, string itemType) 
    { 
     Id = id; 
     ItemType = itemType; 
    } 
} 

ArmorItem.cs

[JsonObject(MemberSerialization.OptIn)] 
public sealed class ArmorItem : Item 
{ 
    [JsonProperty("defense")] public int Defense { get; } 

    [JsonConstructor] 
    public ArmorItem(int id, string itemType, int defense) : base(id, itemType) 
    { 
     Defense = defense; 
    } 
} 

ItemConverter.cs

public sealed class ItemConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JObject item = JObject.Load(reader); 

     switch (item["type"].Value<string>()) 
     { 
      case "Armor": 
       return item.ToObject<ArmorItem>(); 
      default: 
       return item.ToObject<Item>(); 
     } 
    } 

    public override bool CanConvert(Type objectType) 
     => typeof (Item).IsAssignableFrom(objectType); 
} 

我通常從網絡上獲得的JSON數據,並直接使用WebResponse.GetResponseStream流來反序列化數據。

using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse()) 
using (JsonTextReader reader = new JsonTextReader(new StreamReader(resp.GetResponseStream()))) 
{ 
    return new JsonSerializer().Deserialize<Item>(reader); 
} 

我知道爲什麼發生這個循環,但我無法修復它。
但是我注意到以不同的方式反序列化json數據時,問題不會發生。

string json = "SOME JSON DATA HERE"; 
Item item = JsonConvert.DeserializeObject<Item>(json, new ItemConverter()); 

不幸的是,我可以使用流不能解決現有的代碼,我不希望傳入的JSON數據臨時存儲到一個字符串能夠(Item通過刪除JsonConverter屬性改變了這一點)使用工作代碼。
任何想法如何打破循環?

回答

1

總之,你需要告訴Json.net通過標準轉換器反序列化你的json,而不是你自定義的。雖然不止一種方法去做一件事,這是一個我現在可以提供:

  1. Item刪除JsonConverter(typeof(ItemConverter))。這將允許item.ToObject<Item>()正常工作。

  2. 現在你需要告訴你的外部反序列化使用轉換器。要做到這一點:

    var settings = new JsonSerializerSettings() 
    { 
        Converters = new [] { new ItemConverter() } 
    }; 
    return JsonSerializer.Create(settings).Deserialize<Item>(reader) 
    

    (實際上,你可以緩存設置)