.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
{
    /// <summary>
    /// Resolves the specified property name.
    /// </summary>
    /// <param name="name">The property name to resolve.</param>
    /// <returns>The resolved property name.</returns>
    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
{
    /// <summary>
    /// Resolves the specified property name.
    /// </summary>
    /// <param name="name">The property name to resolve.</param>
    /// <returns>The resolved property name.</returns>
    protected override string ResolvePropertyName(string name)
    {
        return name.ToLower();
    }
}

嗯,全部完成。

额外扩展

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

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

    /// <summary>
    /// Causes child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
    /// </summary>
    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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 .NET 中,你可以使用 `Newtonsoft.Json` 库来进行 JSON 序列和反序列操作。以下是一个示例代码,演示了如何使用自定义格式进行序列和反序列: ```csharp using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; // 自定义数据类 public class Person { public string Name { get; set; } public int Age { get; set; } public List<string> Hobbies { get; set; } } // 自定义序列器 public class CustomSerializer : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { if (objectType == typeof(List<string>)) { return new JsonPrimitiveContract(typeof(string)); } return base.CreateContract(objectType); } } class Program { static void Main(string[] args) { // 自定义数据 var person = new Person { Name = "John", Age = 30, Hobbies = new List<string> { "reading", "painting", "coding" } }; // 自定义格式的 JSON 序列 var settings = new JsonSerializerSettings { ContractResolver = new CustomSerializer(), Formatting = Formatting.Indented }; var json = JsonConvert.SerializeObject(person, settings); Console.WriteLine(json); // 输出:{"Name":"John","Age":30,"Hobbies":"reading|painting|coding"} // 反序列 var deserializedPerson = JsonConvert.DeserializeObject<Person>(json); Console.WriteLine($"{deserializedPerson.Name}, {deserializedPerson.Age}"); // 输出:John, 30 } } ``` 在上面的示例中,我们定义了一个 `Person` 类来表示自定义数据。然后,我们创建了一个 `CustomSerializer` 类来继承自 `DefaultContractResolver`,并重写了 `CreateContract` 方法,以使列表类型被当作字符串类型进行序列。 在 `Main` 方法中,我们创建了一个 `Person` 对象,并使用 `JsonConvert.SerializeObject` 方法将其序列为 JSON 字符串。我们使用 `JsonSerializerSettings` 来指定自定义的序列器和格式选项。最后,我们使用 `JsonConvert.DeserializeObject` 方法将 JSON 字符串反序列为 `Person` 对象。 请注意,你需要在项目中安装 `Newtonsoft.Json` NuGet 包才能使用 `Newtonsoft.Json` 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值