Json.NET在序列化时获取通用属性类型名称? [英] Json.NET getting generic property types name on serialization?
问题描述
我试图弄清楚如何从我的API中返回一个核心对象
I'm trying to figure out how I can have a core object being returned from my API
public class Response<T> {
public T Data {get;set;}
}
其中T是具有某些属性的对象,例如
Where T is some object with properties e.g.
public class Thang {
public string Thing {get;set;}
}
使用JsonConvert.Serialize( myResponse );
将把T Data
属性返回为Data
,这是正确的.
Using JsonConvert.Serialize( myResponse );
will return the T Data
property as Data
, and rightly so.
但是如果我想为T
类型使用名称该怎么办?因此,响应Json实际上将包括一个名为Thang
而不是Data
的属性,如下所示.
But what If I wanted to use the name for the type of T
? So the response Json would actually include a property called Thang
not Data
as follows.
{
"thang": {
"thing" : "hey"
}
}
我很好奇是否有一种相对简单的方法可以使用 Json.net 或执行此操作您必须创建一个自定义JsonConverter
并在编写时使用反射来获取T
类型名称?
I'm curious if there is a relatively simple way to do this with Json.net or do you have to create a custom JsonConverter
and use reflection to get the T
type name when writing?
谢谢.
推荐答案
我不知道有内置的方法可以做到这一点.
There's no built-in way to do this that I'm aware of.
您确实需要使用一点反射,您可能可以使用自定义的JsonConverter
,但是您也可以使用自定义的ContractResolver
在短短的几行代码中完成它:
You do need to use a little reflection, and you could probably use a custom JsonConverter
, but you could also do it in just a few lines of code using a custom 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;
}
}
然后您可以像这样使用它:
You could then use it like this:
var settings = new JsonSerializerSettings();
settings.ContractResolver = new GenericPropertyContractResolver(typeof(Response<>));
string serialized = JsonConvert.SerializeObject(new Response<Thang>
{
Data = new Thang { Thing = "Hey" }
}, settings);
可能更直接的方法是在序列化类之前将您的类转换为Dictionary
.
Possibly a more straightforward thing to do would be to turn your class into a Dictionary
before serializing it.
确定封闭的泛型类型的属性是否对应于开放的泛型类型的泛型属性时,我也遇到了一些麻烦-对此的任何提示将不胜感激.
I also had a little trouble determining if a property on a closed generic type corresponded to a generic property on the open generic type--any tips on that would be appreciated.
示例: https://dotnetfiddle.net/DejOL2
这篇关于Json.NET在序列化时获取通用属性类型名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!