2015-09-25 59 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) 
    

    (实际上,你可以缓存设置)