json.net – 如何在根对象上添加属性$type ONLY
我想修改我的json.NET序列化程序,只将$type属性添加到实现给定接口但不对任何属性或嵌套对象的对象.
使用TypeNameHandling.Auto(默认) { "PropertyA": 123,"PropertyB": "foo","PropertyC": [1,2,3,4] } 使用TypeNameHandling.All { "$type": "JsonNetTypeNameHandling.TestEvent,jsonNetTypeNameHandling","PropertyA": 123,"PropertyC": { "$type": "System.Collections.Generic.List`1[[System.Int32,mscorlib]],mscorlib","$values": [1,4 ] } } 我想要的是 { "$type": "JsonNetTypeNameHandling.TestEvent,4] } 我正在尝试使用自定义的ContractResolver,但我没有让它工作: class Program { static void Main(string[] args) { var serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto,TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,ContractResolver = new EnableTypeNameHandlingAllOnlyForEvents(),Formatting = Formatting.Indented }; var event1 = new TestEvent() { PropertyA = 123,PropertyB = "foo",PropertyC = new List<int> { 1,4 } }; string event1Serialized = JsonConvert.SerializeObject(event1,serializerSettings); Console.WriteLine(event1Serialized); Console.ReadLine(); } } public interface IEvent { } public class TestEvent : IEvent { public int PropertyA { get; set; } public string PropertyB { get; set; } public List<int> PropertyC { get; set; } } public class EnableTypeNameHandlingAllOnlyForEvents : DefaultContractResolver { protected override JsonObjectContract CreateObjectContract(Type objectType) { var x = base.CreateObjectContract(objectType); if (typeof(IEvent).IsAssignableFrom(x.UnderlyingType)) { // What to do to tell json.NET to add $type to instances of this (IEvent) type??? } return x; } }
如果您需要根对象上的“$type”属性,并且可以在嵌套的多态对象和数组中显示,如果需要,请使用以下重载以及TypeNameHandling.Auto:
JsonConvert.SerializeObject(Object,Type,JsonSerializerSettings) .
从docs开始:
即,做: var serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto,Formatting = Formatting.Indented }; var event1Serialized = JsonConvert.SerializeObject(event1,typeof(IEvent),serializerSettings); 如果在根对象上需要“$type”并且在嵌套的多态对象和数组上不接受它,即使否则需要,您将需要使用TypeNameHandling.All以及设置 public class SuppressItemTypeNameContractResolver : DefaultContractResolver { // As of 7.0.1,Json.NET suggests using a static instance for "stateless" contract resolvers,for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." static SuppressItemTypeNameContractResolver instance; // Using a static constructor enables fairly lazy initialization. http://csharpindepth.com/Articles/General/Singleton.aspx static SuppressItemTypeNameContractResolver() { instance = new SuppressItemTypeNameContractResolver(); } public static SuppressItemTypeNameContractResolver Instance { get { return instance; } } protected SuppressItemTypeNameContractResolver() : base() { } protected override JsonContract CreateContract(Type objectType) { var contract = base.CreateContract(objectType); var containerContract = contract as JsonContainerContract; if (containerContract != null) { if (containerContract.ItemTypeNameHandling == null) containerContract.ItemTypeNameHandling = TypeNameHandling.None; } return contract; } } 然后使用它像: var serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All,ContractResolver = SuppressItemTypeNameContractResolver.Instance,serializerSettings); 最后,请注意Newtonsoft docs中的这一注意事项:
有关为何需要这样做的讨论,请参阅TypeNameHandling caution in Newtonsoft Json,How to configure Json.NET to create a vulnerable web API和AlvaroMu?oz& Oleksandr Mirosh的黑帽纸https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |