当前位置: 首页 > 面试题库 >

Json.NET在序列化时获取通用属性类型名称?

易宣
2023-03-14
问题内容

我试图弄清楚如何从我的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实际上将包含一个名为Thangnot 的属性Data,如下所示。

{
    "thang": {
        "thing" : "hey"
    }
}

我很好奇是否有一个相对简单的方法可以用Json.net做到这一点,或者您是否必须创建一个自定义JsonConverterT在编写时使用反射来获取类型名称?

谢谢。


问题答案:

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

您确实需要使用一点反射,并且您可能可以使用custom JsonConverter,但是您也可以使用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;
    }
}

然后,您可以像这样使用它:

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



 类似资料:
  • 问题内容: 我如何才能序列化一个特定的属性,但又防止其反序列化回POCO?是否可以使用属性装饰特定属性? 基本上,我正在寻找一个与ShouldSerialize *方法等效的反序列化方法。 我知道我可以编写一个自定义转换器,但是这样做似乎有点过头了。 编辑: 这里还有一些背景。这背后的原因是我的课看起来像: 我需要请求的属性,但是我不希望它反序列化并触发设置程序逻辑。 问题答案: 最简单的方法是将

  • 问题内容: 我正在使用JSON.NET对对象进行序列化以连接到REST API。我对象中需要序列化为JSON的属性之一具有动态属性名称。如果此属性的struct中包含的值是数字值,则JSON属性为“ type_id”,但是,如果此值是字符串值,则JSON属性名称为“ type_code”。我尝试为此使用自定义,但是在尝试序列化时收到以下消息: “状态为Property的令牌PropertyName

  • Json.net有没有办法只指定你想要序列化的属性?或者根据绑定标志序列化某些属性,比如只声明? 现在我正在使用< code > JObject。FromObject(MainObj。SubObj);要获取SubObj的所有属性,SubObj是遵循ISubObject接口的类的实例: 如果是,它将序列化A和B,但如果是,它将仅序列化B和C并忽略父属性

  • 问题内容: 我有一个用作调用RESTful Web服务的 模板 。这是通过解析器创建的,由于它被用作告诉用户端点模式的模板,因此我不得不想出一种保留所有属性的方法,这就是为什么将其默认值设置为的原因。作为示例,这是对象最初的外观: 然后,用户可以根据需要填写各个字段,例如和: 表示他们只关心这两个领域。现在,我想将此模板()序列化回一个JSON字符串,但只希望显示填充的那些字段。所以我尝试了这个:

  • 问题内容: 我正在使用Newtonsoft.Json序列化程序将C#类转换为JSON。对于某些类,我不需要将序列化器设置为具有单个属性的实例,而只需在对象上调用ToString,即 我应该怎么做才能使Person对象序列化为其ToString()方法的结果?我可能有许多这样的类,所以我不想以特定于Person类的序列化器结尾,我想拥有一个可以应用于任何类的序列化器(我想通过属性)。 问题答案: 您

  • 关于这个问题: 如何在使用JSON.NET序列化时更改属性名称? 会像预期的那样反序列化。 作为一个解决方案,没有属性也可以工作,或者类上有一个属性,比如: