【问题标题】:C# JSON.NET How to ignore a property in deserialization but not in serializationC# JSON.NET 如何在反序列化中忽略属性但在序列化中不忽略
【发布时间】:2019-11-26 09:51:03
【问题描述】:

我有一个对象要序列化为 JSON,然后反序列化。

其中一个属性的结构发生了变化,现在反序列化崩溃了,所以我现在需要忽略反序列化该属性。

我可以使用 [JsonIgnore, JsonProperty(Required = Required.Default)] 完全忽略该属性,但这也忽略了序列化的属性 - 它需要保留,因此不会丢失任何数据,即使此时它没有被序列化。

【问题讨论】:

  • @AmadeuAntunes 从标题我认为完全相反

标签: c# json json.net


【解决方案1】:

这里有一个答案,虽然它有点旧:https://stackoverflow.com/a/31732029/12431728 但是,它对我来说似乎仍然可行,我不知道有更好/不同的方法来做到这一点。该答案建议使用 JsonIgnore 标记真实属性并创建“仅获取代理属性”。

如果您需要为许多属性使用此功能(AKA 可重用解决方案),它会继续建议创建自定义 ContractResolver。

【讨论】:

  • 嘿,Matt 很棒的建议,我现在正在研究自定义 ContractResolver
  • @moffin 你不希望最终能够从 json 反序列化你的属性吗?如果是这样,这里似乎更像是您想要一种从 json 中分配数据(如果存在)的方法,如果不存在则忽略。具有可访问 getter 的被忽略属性似乎并不能真正提供此功能
  • @Jack 我想忽略数据,即使它存在。特定字段已从字符串更改为对象,我现在只想忽略加载它,同时仍然保存它
【解决方案2】:

您可以使用 JsonContractResolver 设置 JsonProperty.ShouldDeserialize 属性,如 Newtonsoft.Json 的 test suites 之一所示。

例如,

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

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        MethodInfo shouldDeserializeMethodInfo = member.DeclaringType.GetMethod("ShouldDeserialize" + member.Name);

        if (shouldDeserializeMethodInfo != null)
        {
            property.ShouldDeserialize = o => { return (bool)shouldDeserializeMethodInfo.Invoke(o, null); };
        }

        return property;
    }
}

示例代码

var instance = new RootObject { ID = 2, DisplayName = "John Doe" };
var json = JsonConvert.SerializeObject(instance);
var settings = new JsonSerializerSettings
{
  ContractResolver = ShouldDeserializeContractResolver.Instance
};
Console.WriteLine(json);

var deserializedInstance = JsonConvert.DeserializeObject<RootObject>(json, settings);
Console.WriteLine($"Deserialized => Id={deserializedInstance.ID}, Name={deserializedInstance.DisplayName} ");

RootObject定义为

public class RootObject
{
    public int ID { get; set; }
    public string DisplayName { get; set; }

    public bool ShouldDeserializeDisplayName() => false;    
}

输出

{"ID":2,"DisplayName":"John Doe"}  //During Serialization
Deserialized => Id=2, Name=        // During Deserialization  

【讨论】:

    【解决方案3】:

    您可以像在 Amadeu Antunes 的 link 中一样从 JObject 序列化和反序列化,尽管这种解决方案相当不雅,因为突然之间您已经将松散的类型混入其中。

    另一种可能更容易的可能性是,如果您可以访问要反序列化的所有 json 对象,则可以在 notepad++、ssms 或其他任何内容中进行批量更新,然后将一些默认值添加到 json 文件中。

    【讨论】:

      猜你喜欢
      • 2013-08-17
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-07
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      相关资源
      最近更新 更多