Json.NET正在序列化时获取泛型属性类型名称



我正在试图弄清楚如何从我的API 返回一个核心对象

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类型名称?

谢谢。

据我所知,没有内置的方法可以做到这一点。

您确实需要使用一点反射,您可能会使用自定义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

相关内容

  • 没有找到相关文章

最新更新