【问题标题】:ISerializable and JsonObject/JsonProperty JSON.NETISerializable 和 JsonObject/JsonProperty JSON.NET
【发布时间】:2021-06-08 04:20:18
【问题描述】:

我们的对象既依赖于 ISerializable(将接口标记为可序列化的实现者),内部也有 JsonObject 和 JsonProperty 属性。举个例子:

[JsonObject("Example")]
[Serializable]
public class Example : ISerializable
{
    [JsonProperty("TEST")]
    string _testString;

    public string TestString
    {
        get => _testString;
        set => _testString = value;
    }

    protected Example(SerializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException(nameof(info), $"{nameof(info)} is null.");
        }

        _testString = info.GetString(nameof(TestString));
    }

    protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(TestString), _testString);
    }

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException(nameof(info), $"{nameof(info)} is null.");
        }

        GetObjectData(info, context);
    }
}

那么有没有办法强制 Json 序列化程序使用 ISerializable 接口或属性。如果没有强制执行的选项,也许可以选择优先考虑不同的机制?

更新

根据下面的一条评论,我添加了一个合同解析器,但这会导致我的序列化字符串中的内容错误/缺失 - 我想我以错误的方式使用合同解析器?

public class ContractResolver : IContractResolver
{
    public JsonContract ResolveContract(Type type)
    {
        if(typeof(ISerializable).IsAssignableFrom(type))
        {
            return new JsonISerializableContract(type);
        }
        return new JsonObjectContract(type);
    }
}

【问题讨论】:

  • 不完全清楚ISerializable(假设stackoverflow.com/questions/810974/…)与文本序列化的关系......
  • 与文本序列化无关。它只是意味着对象可以被序列化——我认为这也是 JSON.NET 支持这个接口的原因。所以我不太明白你的评论?
  • 为什么需要两种方式?是否要根据所选选项对对象进行不同的序列化?
  • @PeterCsala:这正是我想要实现的目标。
  • 我认为您需要实现自定义合同解析器并覆盖CreateContract 方法。如果是ISerializable,则需要使用JsonISerializableContract,否则使用JsonObjectContract

标签: c# json serialization json.net


【解决方案1】:

如果您想创建自定义逻辑,您需要通过从DefaultContractResolver 派生来创建您的IContractResolver。然后覆盖受保护的CreateContract 方法而不是ResolveContract

例如,以下解析器将ISerializable 优先于[JsonObject] 属性(在base implementation 中是相反的)。

public class CustomContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type type)
    {
        JsonContract contract = base.CreateContract(type);
        if (!IgnoreSerializableInterface &&
            typeof(ISerializable).IsAssignableFrom(type) && 
            !(contract is JsonDictionaryContract))
        {
            return CreateISerializableContract(type);
        }
        return contract;
    }
}

【讨论】:

  • 看来这几乎可以工作了。无论如何,对于字典,customcontractresolver 的输出与默认值相比是不同的。使用 customcontractresolver 时,还会输出类似 " "Version": 2, "Comparer": { "$type": "System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib]], mscorlib" }, " HashSize": 3,"
  • 另一个小评论。而不是调用“return new JsonISerializableContract(type);”最好调用“return CreateISerializableContract(type);”否则无法反序列化内容。
  • 是的,你是对的——那是一个疏忽。
  • 我已经更新了我的答案,并修复了字典问题。
猜你喜欢
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多