2012-08-30 26 views
2

我正在使用发送JSON的RESTful Web服务,我尝试使用HttpContent.ReadAsAsync<T>进行反序列化。我尝试反序列化的类型声明一个返回包含接口类型的IEnumerable的属性。此代码片段演示的那种类型的,我尝试反序列化到:使用Newtonsoft.Json,如何将JSON反序列化为包含接口类型的IEnumerable属性的类型?

public class Data 
{ 
    public IEnumerable<IChild> Children { get; set; }; 
} 

的问题是,Newtonsoft.Json,基础HttpContent.ReadAsAsync<T>不知道如何反序列化IChild类型的对象,后者是一个接口。我如何指定Newtonsoft.Json如何将IChild反序列化为具体类型?

+0

@ L.B在这种情况下是否重要?问题是如何告诉Newtonsoft.Json将接口(IChild)转换为具体类型f.e.x Child。 – aknuds1

+0

@ L.B你认为太多了。 – aknuds1

回答

4

您可以使用自定义Converter来告诉JSON.NET如何反序列化该接口的类型。下面的代码显示了一个例子。

public class StackOverflow_12197892 
{ 
    public class Data 
    { 
     public IEnumerable<IChild> Children { get; set; } 

     public override string ToString() 
     { 
      return string.Format("Data{{Children=[{0}]}}", 
       string.Join(", ", Children.Select(c => string.Format("{0}/{1}", c.Name, c.IsFemale ? "girl" : "boy")))); 
     } 
    } 
    public interface IChild 
    { 
     string Name { get; } 
     bool IsFemale { get; } 
    } 
    public class Son : IChild 
    { 
     public Son(string name) 
     { 
      this.Name = name; 
     } 

     public string Name { get; private set; } 
     public bool IsFemale { get { return false; } } 
    } 
    public class Daughter : IChild 
    { 
     public Daughter(string name) 
     { 
      this.Name = name; 
     } 

     public string Name { get; private set; } 
     public bool IsFemale { get { return true; } } 
    } 
    class ChildConverter : Newtonsoft.Json.JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return typeof(IChild).IsAssignableFrom(objectType); 
     } 

     public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) 
     { 
      JObject obj = serializer.Deserialize<JToken>(reader) as JObject; 
      if (obj != null) 
      { 
       bool isFemale = obj["isFemale"].ToObject<bool>(); 
       string name = obj["name"].ToObject<string>(); 
       if (isFemale) 
       { 
        return new Daughter(name); 
       } 
       else 
       { 
        return new Son(name); 
       } 
      } 
      else 
      { 
       return null; 
      } 
     } 

     public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
    public static void Test() 
    { 
     Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); 
     serializer.Converters.Add(new ChildConverter()); 
     string json = "{'Children':[{'name':'John',isFemale:false},{'name':'Mary',isFemale:true}]}".Replace('\'', '\"'); 
     var obj = serializer.Deserialize(new StringReader(json), typeof(Data)); 
     Console.WriteLine(obj); 
    } 
} 
+0

谢谢。你将如何整合与'HttpContent.ReadAsAsync '虽然转换器,因为这要求Newtonsoft.Json间接? – aknuds1

+0

您需要在内容的格式化程序中设置转换器。 – carlosfigueira

+0

我通过设置'[ConverterAttribute]''上配置IChild'的转换器。 – aknuds1

0

这是很简单的进出由json.net提供的内置支持,你只需要使用下面的JsonSettings在序列化和反序列化:

JsonConvert.SerializeObject(graph,Formatting.None, new JsonSerializerSettings() 
                           { 
                           TypeNameHandling = TypeNameHandling.Objects, 
                           TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple 
                          }); 

和Deserialzing使用下面的代码:

JsonConvert.DeserializeObject(Encoding.UTF8.GetString(bData),type, 
                 new JsonSerializerSettings() 
                  {TypeNameHandling = TypeNameHandling.Objects}); 

只需记下JsonSerializerSettings对象初始值设定项,这对您很重要。

相关问题