序列化json时如何忽略JsonProperty(PropertyName = "someName")?

Posted

技术标签:

【中文标题】序列化json时如何忽略JsonProperty(PropertyName = "someName")?【英文标题】:How to ignore JsonProperty(PropertyName = "someName") when serializing json? 【发布时间】:2014-01-04 12:38:37 【问题描述】:

我有一些使用 ASP.Net MVC 的 C# 代码,它利用 Json.Net 序列化一些 DTO。为了减少负载,我使用了 [JsonProperty(PropertyName = "shortName")] 属性在序列化过程中使用较短的属性名称。

当客户端是另一个 .Net 应用程序或服务时,这很有效,因为反序列化将对象层次结构重新组合在一起,使用更长更友好的名称,同时保持实际传输负载较低。

当客户端通过浏览器使用 javascript/ajax 时,问题就出现了。它发出请求,并获取 json ...但该 json 使用的是缩短的不太友好的名称。

如何让 json.net 序列化引擎以编程方式忽略 [JsonProperty(PropertyName = "shortName")] 属性?理想情况下,我的 MVC 服务将在那里运行并通常使用缩短的属性名称进行序列化。当我的代码检测到特定参数时,我想使用更长的名称序列化数据并忽略 [JsonProperty()] 属性。

有什么建议吗?

谢谢,

凯文

【问题讨论】:

只要去掉JsonProperty,根据你传递的参数返回一个匿名对象即可。类似newUserName=uname 我认为最好的方法是制作一个自定义序列化程序(使用 json.NET,而不是从头开始)并删除注释。将短名称与长名称设置为序列化程序的设置,并在序列化时告诉它您想要哪个。 json.NET 不支持在运行时使用/忽略注释。如果它们在编译时就在那里,它们将被使用(排除一些主要的黑客攻击)。 我很欣赏那里的 cmets。 @evanmcdonnal:如果我们使用自定义序列化程序,我们是否需要在特定于 DTO 的级别上执行此操作(附加到每个 DTO?)我们有许多 DTO,通过我们的许多开发团队分布在许多解决方案中。理想情况下,我们可以找到一种相对优雅的方式来附加到序列化过程中,而无需通过所有 DTO 来接触和维护它。 这可以使用自定义合约解析器来完成。请参阅下面的答案。 @Kevin 这真的取决于,您可以以一般方式执行此操作,而无需对 DTO 进行任何更改。在我的代码库中,在 json.NET 之上有一些抽象。如果我要这样做,我将在该级别进行更改,并且我会在序列化程序中执行某些操作,例如使用反射获取属性名称,然后获取该属性的子字符串以获取短名称。当然,失去对短名称的控制权会有一些小的权衡,但这将是一个简单的通用解决方案。 【参考方案1】:

这可以使用自定义合约解析器轻松完成。这是您需要的所有代码:

class LongNameContractResolver : DefaultContractResolver

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    
        // Let the base class create all the JsonProperties 
        // using the short names
        IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);

        // Now inspect each property and replace the 
        // short name with the real property name
        foreach (JsonProperty prop in list)
        
            prop.PropertyName = prop.UnderlyingName;
        

        return list;
    

这是一个使用解析器的快速演示:

class Program

    static void Main(string[] args)
    
        Foo foo = new Foo
        
            CustomerName = "Bubba Gump Shrimp Company",
            CustomerNumber = "BG60938"
        ;

        Console.WriteLine("--- Using JsonProperty names ---");
        Console.WriteLine(Serialize(foo, false));
        Console.WriteLine();
        Console.WriteLine("--- Ignoring JsonProperty names ---");
        Console.WriteLine(Serialize(foo, true));
    

    static string Serialize(object obj, bool useLongNames)
    
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.Formatting = Formatting.Indented;
        if (useLongNames)
        
            settings.ContractResolver = new LongNameContractResolver();
        

        return JsonConvert.SerializeObject(obj, settings);
    


class Foo

    [JsonProperty("cust-num")]
    public string CustomerNumber  get; set; 
    [JsonProperty("cust-name")]
    public string CustomerName  get; set; 

输出:

--- Using JsonProperty names ---

  "cust-num": "BG60938",
  "cust-name": "Bubba Gump Shrimp Company"


--- Ignoring JsonProperty names ---

  "CustomerNumber": "BG60938",
  "CustomerName": "Bubba Gump Shrimp Company"

【讨论】:

爱你,布莱恩,因为这个完美的答案。来自开发人员的拥抱 :) Tbh 我希望有一个更简单的解决方案 另外,我认为IgnoreJsonPropertyNameContractResolver 是这个解析器的更好名称。【参考方案2】:

只想用 Deserializer 类“扩展”Brian 的答案,

static T Deserialize<T>(string json)

    return JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings()
    
        ContractResolver = new LongNameContractResolver()
    );

【讨论】:

以上是关于序列化json时如何忽略JsonProperty(PropertyName = "someName")?的主要内容,如果未能解决你的问题,请参考以下文章

使用新的 Net Core 3.0 Json 时忽略属性

忽略单元测试的 Jackon JsonProperty 访问

@JsonProperty 在枚举中被忽略 [重复]

用Jackson进行Json序列化时的常用注解

JSON 对象模型不使用 JsonProperty 名称

C# Newtonsoft.Json JsonSerializerSettings配置