在创建JsonObjectContract时抑制$ type

时间:2014-12-24 03:23:03

标签: c# arrays json.net signalr

我正试图在Json.NET中强制抑制一些特定的$ type输出(同时保留其他输出)。在我的申请中它们是不必要的。 Json.NET源代码显示了这一点:

private bool ShouldWriteType(...)
{
  TypeNameHandling resolvedTypeNameHandling =
    ((member != null) ? member.TypeNameHandling : null)
    ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
    ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
    ?? Serializer._typeNameHandling;

这让我觉得我可以通过在容器合同中设置ItemTypeNameHandling来覆盖序列化设置。唉,它不适用于数组。我尝试重写方法以获取数组合同,但是那里的设置会影响数组中的每个项目。那不是我想要的。 (并且SignalR在对象数组中发送所有方法参数。)这是我的完整演示代码,其中我试图弄清楚如何在输出中保留A的类型但是抑制{{1}的类型}(以及所有B个类)。如何覆盖合同解析程序以正确执行此操作?

sealed

更新:在更多地研究了Json.NET代码之后,using System; using System.Diagnostics; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace DemoBadTypeInclusion { class A { public int P1 { get; set; } } // this attribute doesn't work and I don't want to have to reference Json.NET in my POCO //[JsonObject(ItemTypeNameHandling = TypeNameHandling.None)] sealed class B { public int P2 { get; set; } } internal class DtoContractResolver : DefaultContractResolver { protected override JsonObjectContract CreateObjectContract(Type objectType) { var contract = base.CreateObjectContract(objectType); if (objectType.IsSealed && objectType.BaseType == typeof(object)) { contract.ItemTypeNameHandling = TypeNameHandling.None; } return contract; } } class Program { static void Main() { var objs = new object[] {new A {P1 = 3}, new B {P2 = 4}}; var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, NullValueHandling = NullValueHandling.Ignore, TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, ContractResolver = new DtoContractResolver(), }; var json = JsonConvert.SerializeObject(objs, settings); Console.WriteLine(json); if (Debugger.IsAttached) Console.ReadKey(); } } } 的这一行似乎是我遇到麻烦的原因:

SerializeList

我想要后备值(JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); )。有谁知道怎么做GetContractSafe null?

1 个答案:

答案 0 :(得分:2)

如果禁止对象Array的一个类型引用,则会使孔Array不可序列化。 所以你可以抑制数组的所有类型引用。

仅抑制对象数组的类型引用

protected override JsonArrayContract CreateArrayContract(Type objectType)
{
            var c = base.CreateArrayContract(objectType);

            if(objectType == typeof(Object[]))
                c.ItemTypeNameHandling = TypeNameHandling.None;

            return c;
}

如果您不需要反序列化回原始对象,只需设置

即可
new JsonSerializerSettings
{
  TypeNameHandling = TypeNameHandling.None,
  ...
};

我知道这不是一个确切的答案,但我认为没用 用于标识具有反序列化类型的对象数组的一些元素的组件。 所以我认为,这就是为什么它不受json.net支持

毕竟这是一种解决方法,只能抑制一种类型:

static void Main()
        {
            var objs = new object[] { new A { P1 = 3 }, new B { P2 = 4 } };

            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                NullValueHandling = NullValueHandling.Ignore,
                TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
                ContractResolver = new DtoContractResolver(),
            };


            var serial = JsonSerializer.Create(settings);

            var jsonArray = new JArray();


            foreach (var obj in objs)
            {
                if (obj != null && obj.GetType().IsSealed && obj.GetType().BaseType == typeof(object))
                    serial.TypeNameHandling = TypeNameHandling.None;
                else
                    serial.TypeNameHandling = TypeNameHandling.Objects;

                jsonArray.Add(JObject.FromObject(obj, serial));
            }

            var json = jsonArray.ToString(Formatting.None);
            Console.WriteLine(json);

            if (Debugger.IsAttached)
                Console.ReadKey();
        }