2014-10-29 80 views
3

我试图找出我怎么能有一个核心对象从我的APIJson.NET在序列化中获取泛型属性类型的名称?

public class Response<T> { 
    public T Data {get;set;} 
} 

其中T是一些对象,具有例如属性返回

public class Thang { 
    public string Thing {get;set;} 
} 

使用JsonConvert.Serialize(myResponse);将返回T Data财产Data,这是正确的。

但是如果我想使用名称为T的类型?因此,Json的反应实际上包括一个名为Thang而不是Data的属性,如下所示。

{ 
    "thang": { 
     "thing" : "hey" 
    } 
} 

我很好奇,如果有一个比较简单的方法,用Json.net做到这一点还是你必须创建一个自定义JsonConverter和使用反射写作时,为了获得T类型的名字吗?

谢谢。

回答

1

有没有内置的方式来做到这一点,我知道。

你需要使用一个小的反射,你可能可以使用自定义JsonConverter,但你也可以使用自定义ContractResolver做到在短短的几行代码:

public class GenericPropertyContractResolver : 
     CamelCasePropertyNamesContractResolver 
{ 
    private readonly Type genericTypeDefinition; 

    public GenericPropertyContractResolver(Type genericTypeDefinition) 
    { 
     this.genericTypeDefinition = genericTypeDefinition; 
    } 

    protected override JsonProperty CreateProperty(
     MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty baseProperty = 
      base.CreateProperty(member, memberSerialization); 

     Type declaringType = member.DeclaringType; 

     if (!declaringType.IsGenericType || 
      declaringType.GetGenericTypeDefinition() != this.genericTypeDefinition) 
     { 
      return baseProperty; 
     } 

     Type declaringGenericType = declaringType.GetGenericArguments()[0]; 

     if (IsGenericMember(member)) 
     { 
      baseProperty.PropertyName = 
       this.ResolvePropertyName(declaringGenericType.Name); 
     } 

     return baseProperty; 
    } 

    // Is there a better way to do this? Determines if the member passed in 
    // is a generic member in the open generic type. 
    public bool IsGenericMember(MemberInfo member) 
    { 
     MemberInfo genericMember = 
      this.genericTypeDefinition.GetMember(member.Name)[0]; 

     if (genericMember != null) 
     { 
      if (genericMember.MemberType == MemberTypes.Field) 
      { 
       return ((FieldInfo)genericMember).FieldType.IsGenericParameter; 
      } 
      else if (genericMember.MemberType == MemberTypes.Property) 
      { 
       PropertyInfo property = (PropertyInfo)genericMember; 

       return property 
        .GetMethod 
        .ReturnParameter 
        .ParameterType 
        .IsGenericParameter; 
      } 
     } 

     return false; 
    } 
} 

,那么你可以使用这样的:

var settings = new JsonSerializerSettings(); 
settings.ContractResolver = new GenericPropertyContractResolver(typeof(Response<>)); 

string serialized = JsonConvert.SerializeObject(new Response<Thang> 
{ 
    Data = new Thang { Thing = "Hey" } 
}, settings); 

可能是一个更简单的事情是把你的类变成Dictionary序列化之前。

我也有点麻烦,如果一个封闭的泛型类型的属性对应于一个泛型属性的开放泛型类型 - 任何提示,将不胜感激。

例如:https://dotnetfiddle.net/DejOL2

相关问题