c# – 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 not 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);

可能更直接的做法是在序列化之前将您的类转换为字典.

我在确定封闭泛型类型上的属性是否与开放泛型类型的通用属性相对应时也遇到了一些麻烦 – 任何提示都会受到赞赏.

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

点赞