实施反序列化抽象类或接口的实现的JsonConverter

时间:2018-10-07 21:32:06

标签: c# json serialization json.net deserialization

我正在尝试创建一个如下所示的JsonConverter

  • 仅适用于abstractclassinterface s
  • 以“默认”方式写入JSON
  • 通过查找所有派生的具体类并尝试将其反序列化为JSON来读取JSON。使用第一个有效的方法,或者如果有多个有效方法,则抛出错误(使用一种方法来覆盖此设置,而采用第一个有效的方法)。
  • 它不是递归工作的,这意味着任何抽象或接口的类属性都需要使用该属性标记

其工作方式示例:

如果有

    /// <summary>
    /// Interface with multiple non-conflicting implementations
    /// </summary>
    [JsonConverter(typeof(PolyJsonConverter))]
    private interface IBar
    {
        string StringProperty { get; }
    }

    private class Bar1 : IBar
    {
        public string StringProperty { get; set; }

        public string OtherStringProperty { get; set; }
    }

    private class Bar2 : IBar
    {
        public string StringProperty { get; set; }

        public double[] DoubleArrayProperty { get; set; }
    }

然后这是应该通过的测试

    [TestMethod]
    public void InterfaceWithNonConflictingImplementationsDerivedFromOtherInterfaceCanSerializeAndDeserializeToBaseInterfaceTest()
    {
        var concreteBaz = new Baz1()
        {
            StringProperty = "blah blah",
            IntArrayProperty = new int[] { 1, 2, 3 }
        };

        string json = JsonConvert.SerializeObject(concreteBaz);

        IBar bar = JsonConvert.DeserializeObject<IBar>(json);

        Assert.IsNotNull(bar);
        Assert.AreEqual(concreteBaz.StringProperty, bar.StringProperty);
    }

除了ReadJson

中存在无限循环外,我尝试了几乎所有的方法
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);

        string json = jObject.ToString();

        var derivedTypes = GetDerivedTypes(objectType);

        object match = null;

        foreach (var dervivedType in derivedTypes)
        {
            object deserialized;

            try
            {
                deserialized = JsonConvert.DeserializeObject(json, dervivedType, requiredSerializerSettings);
            }
            catch
            {
                continue;
            }

            if (match != null)
            {
                if (conflictResolutionMode == ConflictResolutionMode.ThrowError)
                {
                    throw new JsonException($"Multiple matching implementations found for base type {objectType}.");
                }
            }
            else
            {
                match = deserialized;

                if (conflictResolutionMode == ConflictResolutionMode.UseArbitrary)
                {
                    break;
                }
            }
        }

        if (match == null)
        {
            throw new JsonException($"Could not find match for type {objectType} among derived types {string.Join(", ", derivedTypes)}.");
        }

        return match;
    }

    private static IEnumerable<Type> GetDerivedTypes(Type baseType)
    {
        return derivedTypesCache.GetOrAdd(baseType, t => QueryDerivedTypes(t));
    }

    private static IEnumerable<Type> QueryDerivedTypes(Type baseType)
    {
        return from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
               from assemblyType in domainAssembly.GetTypes()
               where baseType.IsAssignableFrom(assemblyType)
                 && !assemblyType.IsInterface
                 && !assemblyType.IsAbstract
               select assemblyType;
    }

我理解“为什么”,但我不知道如何解决。有什么想法吗?

0 个答案:

没有答案