- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我注意到,默认情况下,JSON.NET 只会(反)序列化对象的公共(public)属性。这很好。但是,当属性被标记为 [JsonPropertyAttribute]
时,JSON.NET 还将访问私有(private) getter 和setter。这很糟糕。
要解决此问题,我想做的是用 [JsonIgnoreAttribute]
标记私有(private) getter/setter。
例如:
public class JsonObject
{
[JsonProperty(PropertyName = "read_write_property")]
public object ReadOnlyProperty
{
get;
[JsonIgnore] private set;
}
}
不幸的是,这不是有效的 C# 代码。那么什么样的代码会达到相同的结果呢?
我知道一些可行的想法:
只有这两个选项吗?
我为只读属性添加了支持字段。不确定,但我想我在 Json.Net 中发现了一个错误。当只有 getter 存在时,序列化程序会将属性视为不存在,即使指定的名称属性与 JSON 字符串匹配。这特别烦人,因为我也在使用 [JsonExtensionData]
机制。所以反序列化的值最终进入了我的扩展数据字典。这是演示问题的代码:
违规类
using System.ComponentModel;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class JsonObject
{
private readonly BindingDirection bindingDirection;
public JsonObject()
{
this.bindingDirection = BindingDirection.OneWay;
}
[JsonProperty(PropertyName = "binding_type"), JsonConverter(typeof(StringEnumConverter))]
public BindingDirection BindingDirection
{
get
{
return this.bindingDirection;
}
}
[JsonExtensionData]
public IDictionary<string, object> ExtensionData { get; set; }
}
示范
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
var obj = new JsonObject();
var serialized = JsonConvert.SerializeObject(obj);
var deserialized = JsonConvert.DeserializeObject<JsonObject>(serialized);
Console.WriteLine("*** Extension data ***\n");
foreach (var kvp in deserialized.ExtensionData)
{
Console.WriteLine("{0} == {1}", kvp.Key, kvp.Value);
}
Console.ReadLine();
}
}
输出
*** Extension data ***
binding_type == OneWay
最佳答案
Json.Net 在使用 [JsonProperty]
属性标记时访问私有(private)成员的事实实际上是设计使然。此功能的存在是为了使 Json.Net 能够用于序列化/反序列化对象的内部状态(例如,持久化它),而无需公开该状态的公共(public)接口(interface)。
来自documentation :
JsonPropertyAttribute
JsonPropertyAttribute has a number of uses:
By default the JSON property will have the same name as the .NET property. This attribute allows the name to be customized.
Indicates that a property should be serialized when member serialization is set to opt-in.
Includes non-public properties in serialization and deserialization.
Customize type name, reference, null and default value handling for the property value.
Customize the property's collection items JsonConverter, type name handing and reference handling.
不幸的是,[JsonProperty]
属性的参数显然没有提供一种方法来选择不包括非公共(public)成员,同时仍然允许您使用其他功能,例如更改属性名称。因此,在这种情况下您将不得不使用变通方法。
您已经提到了几种可能性,我将添加第三种可能性:
[JsonPropertyAttribute]
JsonConverter
为你的类(class)其中,第二个是最干净、最容易实现的,同时仍能实现您正在寻找的结果:公共(public)属性将使用自定义属性名称进行序列化,而私有(private)支持字段在反序列化期间不会受到影响。
第一个选项,即删除属性,不会完全满足您的需求。虽然它会阻止字段被反序列化,但您将不得不接受在序列化期间写入 JSON 的原始属性名称。
第三个选项是编写一个转换器,让您可以完全控制类的序列化和反序列化方式。您可以更改属性名称,省略属性,包括甚至不在类中的其他信息,等等。它们并不难写;但是,如果您真正需要的只是一个简单的支持字段来解决您的问题,那么转换器在这里可能有点过分了。也就是说,如果您真的对此选项感兴趣,我很乐意提供一个简单的示例。请告诉我。
关于您的扩展数据问题——您是对的,这看起来确实像一个错误。当我最初尝试重现该问题时,我做不到,因为我的 JsonObject
版本不包含默认构造函数。我假设你的构造函数有一个参数来接受只读属性的初始值。一旦我删除了参数,它就开始出现异常。我不确定为什么构造函数会对 JsonExtensionData 的解释方式产生影响。但是,这确实提出了一个奇怪的解决方法:尝试将以下内容添加到您的类中,看看是否能解决问题。
[JsonConstructor]
private JsonObject(string dummy) : this()
{
}
关于c# - 使用 JsonIgnoreAttribute 标记私有(private) setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22489595/
我正在使用 JSON.net 来序列化我的 EntityFramework 对象。 过去,我创建了一个将“JsonIgnore”属性应用于属性的类,然后将主 EntityFramework 类的“Me
我注意到,默认情况下,JSON.NET 只会(反)序列化对象的公共(public)属性。这很好。但是,当属性被标记为 [JsonPropertyAttribute] 时,JSON.NET 还将访问私有
我是一名优秀的程序员,十分优秀!