.NET 在序列化时使用全小写的属性名

基于某些奇怪的需求,需要将一些对象序列化后输出,而且属性名又必须为小写形式。

解决过程

说到在 .NET 平台上序列化操作,那么第一个想到的应该就是 Json.NET 家的 Newtonsoft.Json 啦。

首先,我们有这么一个需要序列化的对象。

public class Demo
{
    public int Id { get; set; }

    public string PrimaryKey { get; set; }

    public int WwW { get; set; }
}

那么,我们在平常一般使用时会使用 [JsonProperty(PropertyName="xxx")][JsonIgnore] 等属性来进行一些简单的调整,如下。

public class Demo
{
    [JsonProperty(PropertyName="id")]
    public int Id { get; set; }

    [JsonProperty(PropertyName="primarykey")]
    public string PrimaryKey { get; set; }

    [JsonProperty(PropertyName="www")]
    public int WwW { get; set; }
}

当然这样是可以实现最终效果的,但是当有相当多个地方需要使用小写的属性名时,这么做显然是很坑的 = =

于是,通过各种翻查资料,我发现了一个 Newtonsoft.Json 自带的 CamelCasePropertyNamesContractResolver 类 —— 在序列化时使用驼峰式命名来代替默认的命名方式。

string json = JsonConvert.SerializeObject(
    new Demo { Id = 1, PrimaryKey = "Poi", WwW = 233 },
    new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
    );

如此序列化,输出结果为 { id:1, primaryKey:"Poi", wwW:233 }

显然,这也并不是我们需要的。

不过,观察上面的代码,我们也可以发现 ContractResolver 属性可以自定义格式化序列化后的返回值,而 CamelCasePropertyNamesContractResolver 则继承自 DefaultContractResolver

于是我们定位到 DefaultContractResolver 下,又会发现有一个 NamingStrategy 属性,其介绍为 Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized. 是的,这就是我们需要进行重写的类。

public class NamingStrategyToLower : NamingStrategy
{
    /// 
    /// Resolves the specified property name.
    /// 
    /// The property name to resolve.
    /// The resolved property name.
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLower();
    }
}

显而易见的,我们可以发现这个 ResolvePropertyName(string name) 就是我们需要 override 的方法,而我们需要做的也仅仅只是 return name.ToLower() 将属性名以小写的方式返回而已。

于是,我们最终的调用与输出结果如下。

class Program
{
    static void Main(string[] args)
    {
        string json = JsonConvert.SerializeObject(
            new Demo { Id = 1, PrimaryKey = "Poi", WwW = 233 },
            Formatting.Indented,
            new JsonSerializerSettings { ContractResolver = new ToLowerPropertyNamesContractResolver() }
            );
        Console.WriteLine(json);
        // output
        // {
        //   id:1, 
        //   primarykey:"Poi",
        //   www:233 
        // }
        Console.ReadKey();
    }
}

public class ToLowerPropertyNamesContractResolver : DefaultContractResolver
{
    public ToLowerPropertyNamesContractResolver()
    {
        base.NamingStrategy = new NamingStrategyToLower();
    }
}

public class NamingStrategyToLower : NamingStrategy
{
    /// 
    /// Resolves the specified property name.
    /// 
    /// The property name to resolve.
    /// The resolved property name.
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLower();
    }
}

嗯,全部完成。

额外扩展

细心的pong友们应该发现了,我们使用了 SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings) 的重载来代替之前的 SerializeObject(object value, JsonSerializerSettings settings) 方法。

/// 
/// Specifies formatting options for the Newtonsoft.Json.JsonTextWriter.
/// 
public enum Formatting
{
    /// 
    /// No special formatting is applied. This is the default.
    /// 
    None = 0,

    /// 
    /// Causes child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
    /// 
    Indented = 1
}

从介绍可知,Formatting.Indented 可以帮助我们更加“视觉化”的输出 json

// Formatting.None 也就是默认值
{ id:1, primarykey:"Poi", www:233 }

// Formatting.Indented,格式化输出
{
  id:1, 
  primarykey:"Poi",
  www:233 
}

参考

  1. Serialization Attributes
  2. Serialization using ContractResolver
  3. DefaultContractResolver Class

转载于:https://www.cnblogs.com/yeshiyu/p/7944373.html

你可能感兴趣的:(.NET 在序列化时使用全小写的属性名)