我正试图在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?
答案 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();
}