基础 Class 序列化问题 - 不序列化派生 Class 属性

Base Class Serialization Issue - do not serialize Derived Class Properties

我厌倦了序列化相当大的实体列表,这些实体都是从基础 class 派生的。 我只需要客户端中的基本 class 属性。如何在不实例化基础 class?

的新实例的情况下实现此目的

我试过创建自定义 ContractResolver,但它似乎在运行时执行 getType(),而不是使用正在序列化的 list/Array 的类型

请参阅下面的代码示例。

我要实现。 castBaseString == actualBaseString ;

所以我希望 castBaseString = [{"Id":1},{"Id":2}] 而不是 [{"Value":"value","Id":1},{"Value":"value2","Id":2}]

using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Newtonsoft.Json;


namespace Tests {

    [TestClass]
    public class JsonNetTest {
        class Base {
            public int Id { get; set; }
        }

        class Derived : Base {
            public string Value { get; set; }
        }
        
        class OtherDerived : Base {
            public string Value { get; set; }
            public string OtherValue { get; set; }
        }

        [TestMethod]
        public void Test() {
            IEnumerable<Derived> deriveds = new Derived[] {
                new Derived {Id = 1, Value = "value" },
                new Derived {Id = 2, Value = "value2" }
            };

            IEnumerable<Base> castBases = deriveds.Cast<Base>().ToList();

            IEnumerable<Base> bases = new Base[] {
                new Base {Id = 1 },
                new Base {Id = 2 }
            };
            JsonSerializerSettings s = new JsonSerializerSettings();

            var derString = JsonConvert.SerializeObject(deriveds, s);
            var castBaseString = JsonConvert.SerializeObject(castBases, s);
            var actualBaseString = JsonConvert.SerializeObject(bases, s);

            Assert.AreEqual(actualBaseString, castBaseString);
            Assert.AreNotEqual(castBaseString, derString);
        }
    }
}

根据评论进行编辑 附加上下文:
为了清楚起见,我刚刚发布了这个简单的测试用例。 正在使用的实际上下文是在 aspnet 核心应用程序中。

假设有 3 个控制器

  1. /api/DerivedController/
  2. /api/OtherDerivedController/
  3. /api/BaseController/

当一个客户端调用1时,我们想要return一个Derived的列表,当一个客户端调用 2 我们想要 return OtherDerived 的列表,当他们调用 3,我们想要 return Base 的列表

数据存储在数据库中的 2 个不同表中 TBL_DERIVED 和 TBL_OTHERDERIVED。

当他们调用base时,我们想要实现的是return来自这些表中的一个或两个表的数据,但只是这些表的共同属性。

希望这能说明问题。

在 属性 的顶部添加 [JsonIgnore]

class Derived : Base {
    [JsonIgnore]
    public string Value { get; set; }
}

如果您不想使用属性,您可以使用 ContractResolver 强制仅对 Base 中的属性进行序列化:

public class DerivedTypeFilterContractResolver<T> : DefaultContractResolver {
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.DeclaringType != typeof(T)) {
            property.ShouldSerialize = instance => false;
        }
        
        return property;
    }
}

然后像这样使用它:

void Main() {

    IEnumerable<Derived> deriveds = new Derived[] {
                new Derived {Id = 1, Value = "value" },
                new Derived {Id = 2, Value = "value2" }
            };

    IEnumerable<Base> castBases = deriveds.Cast<Base>().ToList();

    IEnumerable<Base> bases = new Base[] {
                new Base {Id = 1 },
                new Base {Id = 2 }
            };

    JsonSerializerSettings s = new JsonSerializerSettings {
        ContractResolver = new DerivedTypeFilterContractResolver<Base>()
    };

    var derString = JsonConvert.SerializeObject(deriveds, s);
    var castBaseString = JsonConvert.SerializeObject(castBases, s);
    var actualBaseString = JsonConvert.SerializeObject(bases, s);

    Console.WriteLine(castBaseString);
}


class Base {
    public int Id { get; set; }
}

class Derived : Base {
    public string Value { get; set; }
}

输出:

[{"Id":1},{"Id":2}]

事实证明,json 序列化的工作方式是不可能的。 @stuartd 答案可能是一个很好的解决方法,如果你只有有限的情况你想这样做。