我想弄清楚如何从我的 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
在序列化之前。
我在确定封闭泛型类型上的属性是否对应于开放泛型类型上的泛型属性时也遇到了一些麻烦——如果有任何提示,我们将不胜感激。
关于c# - Json.NET 在序列化时获取通用属性类型名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26629430/