【问题标题】:How can I change property names when serializing with Json.net?使用 Json.net 序列化时如何更改属性名称?
【发布时间】:2012-02-06 11:19:20
【问题描述】:

我在 C# DataSet 对象中有一些数据。我现在可以使用这样的 Json.net 转换器对其进行序列化

DataSet data = new DataSet();
// do some work here to populate 'data'
string output = JsonConvert.SerializeObject(data);

但是,当打印到 .json 文件时,它使用来自 data 的属性名称。我想将属性名称更改为不同的名称(例如,将 'foo' 更改为 'bar')。

Json.net documentation 中,在“序列化和反序列化 JSON”→“序列化属性”下显示“JsonPropertyAttribute... 允许自定义名称”。但是没有例子。 有人知道如何使用 JsonPropertyAttribute 将属性名称更改为其他名称吗?

(Direct link to documentation)

Json.net 的文档似乎很少。如果您有一个很好的示例,我会尝试将其添加到官方文档中。 谢谢!

【问题讨论】:

标签: c# serialization json.net


【解决方案1】:

还有另一种方法可以做到这一点,即使用特定的NamingStrategy,可以通过使用[JSonObject][JsonProperty] 装饰类或属性来将其应用于类或属性。

有预定义的命名策略,例如CamelCaseNamingStrategy,但您可以实现自己的。

不同命名策略的实现可以看这里:https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization

【讨论】:

  • 如果可以,请分享一个自定义 NamingStrategy 实现的示例
  • 当然……不是。您应该自己完成,但我会抽出时间告诉您,您只需继承 newtonsoft.com/json/help/html/… 您可以查看现有的类实现,并创建自己的。
  • 谢谢 - 我应该更新我的评论:事实上,感谢 GitHub 的荣耀,我们可以使用 Newtonsoft 自己的实现作为示例,例如,this one
  • @JotaBe,这不是 stackoverflow 的精神。作为一个只想完成我的工作的程序员,坦率地说,提升你可能提供的代码对我来说会好一千倍。你也会得到我的投票。我有 18 年的编码经验,我被 TripleByte 评为 c# 中的“专家”。并不是每个问题都需要作为“读者练习”。有时我们只想做好自己的工作并继续前进。
  • 我同意你的看法,我通常不会写这种评论。但是,我可以保证,在这种情况下,查看链接代码比我能给出的任何解释都要好得多。 json.net 是一个文档非常完善的开源库。包含实现的链接(完美示例)
【解决方案2】:

如果您无权访问类来更改属性,或者不想始终使用相同的重命名属性,也可以通过创建自定义解析器来完成重命名。

例如,如果您有一个名为 MyCustomObject 的类,它有一个名为 LongPropertyName 的属性,您可以使用这样的自定义解析器……

public class CustomDataContractResolver : DefaultContractResolver
{
  public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver ();

  protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
  {
    var property = base.CreateProperty(member, memberSerialization);
    if (property.DeclaringType == typeof(MyCustomObject))
    {
      if (property.PropertyName.Equals("LongPropertyName", StringComparison.OrdinalIgnoreCase))
      {
        property.PropertyName = "Short";
      }
    }
    return property;
  }
}

然后调用序列化并提供解析器:

 var result = JsonConvert.SerializeObject(myCustomObjectInstance,
                new JsonSerializerSettings { ContractResolver = CustomDataContractResolver.Instance });

并且结果将被缩短为 {"Short":"prop value"} 而不是 {"LongPropertyName":"prop value"}

更多关于自定义解析器的信息here

【讨论】:

  • 如果您要序列化的类在另一个包含不同版本的 Newtonsoft.Json 包的程序集中声明,这是一个更好的解决方案。 (它甚至可能不会抛出任何错误)。 DefaultContractResolver 必须放在使用 JsonConvert.Serialize() 方法的同一程序集中。
  • 我正在使用供应商的 API,该 API 有一个供多个 API 函数使用的公共对象。仅在其中一个 API 调用中,公共对象上的一个属性必须序列化为稍微不同的名称(例如 clientid 与 client_id)。这个答案是我问题的完美解决方案。
【解决方案3】:

您可以使用[JsonProperty] 属性来装饰您希望控制其名称的属性,该属性允许您指定不同的名称:

using Newtonsoft.Json;
// ...

[JsonProperty(PropertyName = "FooBar")]
public string Foo { get; set; }

文档:Serialization Attributes

【讨论】:

  • @culix,是的,它确实需要使用模型。 DataSet 是一种弱类型结构,因此为它谈论属性名称不是很合乎逻辑。
  • 简写也可以[JsonProperty("FooBar")]
  • @DarinDimitrov 有没有办法在没有 Json .NET 的情况下做到这一点?
  • 虽然使用模型很简单,只需提取 JSON 样本,然后使用“选择性粘贴”->“将 JSON 粘贴为类”将其粘贴到一个空的 .cs 文件中。 -- 它内置在 Visual Studio 中。 -- 从那里开始,您基本上只需将内容设置为标题大小写/重命名内容以使用 .NET 命名约定等(前者使用标题大小写转换器,后者使用 JsonProperty 属性)。
  • @Homer 在这种情况下这是行不通的,因为关键是能够使用与成员不同的名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多