【问题标题】:Get JSON PropertyName from C# Class, like "nameof(class.prop)" for json properties?从 C# 类获取 JSON 属性名称,例如 json 属性的“nameof(class.property)”?
【发布时间】:2019-02-19 20:45:46
【问题描述】:

如何获取以下类和属性的 JSON PropertyName?类似于 JSON 属性的“nameof()”之类的东西?

比如

var jsonName = GetJSONPropertyName(SampleClass.SampleClassID); //should return "jsoniD"

public class SampleClass
{
    public SampleClass() { }
    [JsonProperty(PropertyName = "jsoniD")]
    public string SampleClassID { get; set; }
}

【问题讨论】:

标签: c# json reflection


【解决方案1】:

一个很好的问题是,如何以类型安全的方式传递属性。属性不是 .NET 中的一流对象。

其中一种方法是:

using System.Linq.Expressions;

// ...

static string GetJsonPropertyName<TC, TP>(Expression<Func<TC, TP>> expr)
{
    if (expr.Body is MemberExpression body)
        return body.Member.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName;
    else
        throw new ArgumentException("expect field access lambda");
}

你需要像这样调用函数:

var jsonName = GetJsonPropertyName<SampleClass, string>(x => x.SampleClassID);

是的,感觉不太自然。很抱歉。


感谢@elgonzo,代码可以这样简化:

static string GetJsonPropertyName<TC>(Expression<Func<TC, object>> expr)
{
    // in case the property type is a value type, the expression contains
    // an outer Convert, so we need to remove it
    var body = (expr.Body is UnaryExpression unary) ? unary.Operand : expr.Body;

    if (body is System.Linq.Expressions.MemberExpression memberEx)
        return memberEx.Member.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName;
    else
        throw new ArgumentException("expect field access lambda");
}

var jsonName = GetJsonPropertyName<SampleClass>(x => x.SampleClassID);

【讨论】:

  • 我猜该方法的签名可以稍微简化,通过将 TP 替换为 objectstatic string GetJsonPropertyName&lt;TC&gt;(Expression&lt;Func&lt;TC, object&gt;&gt; expr) { ... },只需要提供属性作为泛型类型参数的类型。然后调用该方法不需要知道属性类型:GetJsonPropertyName&lt;SampleClass&gt;(x =&gt; x.SampleClassID); 不多,但是像这样的一些小事情有时可以走很长的路... ;-)
  • @elgonzo:确实!我错误地担心x =&gt; x.SampleClassID 不能转换为Func&lt;SampleClass, object&gt;。谢谢!
  • 不确定它是否是 .NET 标准,我的属性是值类型还是其他,但我的 expr.Body 不是 MemberExpression,它是带有 @ 的 UnaryExpression操作数属性中的 987654331@。我已经根据您的回答发布了另一个带有 .NET Standard 解决方案的回复。
【解决方案2】:

Working Value-Type 基于@Vlad 解决方案的表达式支持 (UnaryExpression 模式从 this SO POST 提升)

public static string GetJsonPropertyName<T>(Expression<Func<T, object>> expr)
{
    if (((expr.Body as UnaryExpression)?.Operand ?? expr.Body) is MemberExpression body)
        return body.Member.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName;
    else
        throw new ArgumentException("expect field access lambda");
}

【讨论】:

  • 哦,我明白了:问题是在值类型属性的情况下,我们需要将属性值额外装箱转换为对象。我的答案中的第一个版本的代码在这种情况下也很有效(但需要一个额外的通用参数)。
  • @Vlad,我很抱歉对您的代码进行了改进,但实际上结果证明这是不完整/糟糕的建议。我检查了我自己几年前所做的一些代码,以简化基于评估 lambda 表达式以获取属性名称的 DependencyProperties 的创建,你瞧,我实际上也在那里检查和处理了 UnaryExpressions。我完全忘记了这一点。哎呀...
  • @elgonzo:实际上,我仍然认为您的建议是一种改进:额外检查的成本可以忽略不计,删除额外参数是一件好事!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
  • 2013-06-07
  • 2019-06-02
  • 2012-01-08
  • 2021-12-04
相关资源
最近更新 更多