【问题标题】:Prevent JSON.Net custom converter from converting child objects防止 JSON.Net 自定义转换器转换子对象
【发布时间】:2015-06-12 02:09:50
【问题描述】:

我从一个服务接收 JSON,它是一组搜索结果。 “结果”数组中的每个对象都可以是两种类型的对象之一(我的例子是猫/狗)。下面是一些 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;
        }
    }

我遇到的问题是 Dog 恰好有一个子项 Cat。我的转换器正在捕获这个 Cat 对象并尝试对其进行转换。只有结果对象有“类型”属性,任何子猫或狗的实例都没有这个“类型”属性。缺少此属性会导致空引用异常。

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

【问题讨论】:

    标签: json.net


    【解决方案1】:

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

    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 的实例时才会调用转换器。对于已经声明为Dog 或Cat 类型的成员,其ReadJson() 方法将不会被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      • 2017-06-22
      相关资源
      最近更新 更多