我试图在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
在容器协定中设置来覆盖序列化程序设置。las,它不适用于数组。我尝试重写该方法以获取数组协定,但是那里的设置会影响数组中的每个项目。那不是我想要的 (然后SignalR在对象数组中发送所有方法参数。)这是我的完整演示代码,在这里我试图弄清楚如何A
在输出中保留类型,但抑制B
(和所有sealed
类)的类型。如何覆盖合同解析器以正确执行此操作?
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();
}
}
}
更新:在进一步研究了Json.NET代码之后,看来这一行SerializeList
是我麻烦的根源:
JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
我需要后备值(GetContractSafe
)。有人知道如何使FinalItemContract
null吗?
如果取消对对象Array的一种类型引用,则将使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();
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句