【问题标题】:Json.NET getting generic property types name on serialization?Json.NET 在序列化时获取通用属性类型名称?
【发布时间】:2014-10-29 11:41:43
【问题描述】:

我试图弄清楚如何从我的 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 类型名称?

谢谢。

【问题讨论】:

    标签: c# .net json serialization json.net


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-06
      相关资源
      最近更新 更多