There's no built-in way to do this that I'm aware of.
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);
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.
Example: https://dotnetfiddle.net/DejOL2
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…