防止JSON.Net自定义转换器转换子对象

时间:2015-06-11 17:30:14

标签: json.net

我从服务中接收JSON,这是一组搜索结果。 “结果”数组中的每个对象可以是两种类型的对象之一(我的例子是cat / dog)。以下是JSON的一些示例:

{
  "total": 2,
  "results": [
    {
      "type": "cat",
      "id": "1",
      "name": "Kitty"
    },
    {
      "type": "dog",
      "id": "2",
      "name": "Rover",
      "cat": {
        "id": "3",
        "name": "Missy"
      }
    }
  ]
} 

我将JSON根对象反序列化为“SearchResult”。 "结果"中的每个项目是一个“SearchResultItem”。

这是我的模特喜欢的项目:

public class Cat : SearchResultItem
{
    public string id {get; set;}
    public string name {get; set;}  
}

public class Dog : SearchResultItem
{
    public string id {get; set;}
    public string name {get; set;}
    public Cat {get; set;}  
}

我已经创建了一个自定义转换器,可以为每个对象转换为正确的类型:

public class SearchResultConverter : Newtonsoft.Json.Converters.CustomCreationConverter<SearchResultItem>
    {
        public override SearchResultItem Create(Type objectType)
        {
            throw new NotImplementedException();
        }

        public SearchResultItem Create(Type objectType, JObject jObject)
        {
            var type = (string)jObject.Property("type");
            switch (type)
            {
                case "cat":
                    return new Cat();
                case "dog":
                    return new Dog();
            }

            return null;

            //throw new ApplicationException(String.Format("The given vehicle type {0} is not supported!", type));
        }

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

// Create target object based on JObject
            var target = Create(objectType, jObject);

// Populate the object properties
            serializer.Populate(jObject.CreateReader(), target);

            return target;
        }
    }

我遇到的问题是,狗碰巧有一个猫项目。我的转换器捕获此Cat对象并尝试转换它。只有结果对象具有“type”属性,子Cat或Dog的任何实例都不具有此“type”属性。缺少此属性会导致Null引用异常。

如何将转换器仅限制为“results”数组中的顶级项目?

1 个答案:

答案 0 :(得分:1)

执行此操作最简单的方法可能是覆盖JsonConverter.CanConvert并在typeof(SearchResultItem) == objectType时返回true,而不是从 objectType分配时:

public class SearchResultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(SearchResultItem);
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public SearchResultItem Create(Type objectType, JObject jObject)
    {
        // As before
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // As before
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException("SearchResultConverter should only be used while deserializing.");
    }
}

现在只有在尝试反序列化SearchResultItem的实例时才会调用转换器。对于已声明属于DogCat类型的成员,其ReadJson()方法将不会被调用。