当前位置: 首页 > 编程语言 > C#

JSON.Net自定义合约序列化和集合共享

时间:2023-04-11 10:47:42 C#

JSON.Net自定义合约序列化和集合我正在尝试创建一个IContractResolver来简化我的WebApi项目的安全处理。我想做什么:我想根据一组动态条件(例如,调用端点的用户的角色)序列化某些对象/属性。因此,我实现了一个在接口的CreateProperty覆盖中检查的自定义属性,并将ShouldSerialize函数设置为我自己的逻辑。我现在的问题是,是否可以有条件地序列化某个列表中的完整对象?我不想在预处理步骤中过滤列表(如果我更改我的对象,这很容易出错),我希望它由当前的ContractResolver递归处理。在某种程度上,我试图得到这样的东西://CustomLogic}}我错过了一个覆盖,这根本不可能吗?有没有更好的方法来实际执行此操作而不必“预解析”我所有的值?这不是开箱即用的。如果您检查JsonSerializerInternalWriter.SerializeList()的源代码,您会发现没有基于某些过滤器跳过集合条目的逻辑。然而,Json.NET确实具有强大的异常处理功能。如果在开始序列化对象时抛出异常,它会在[OnError]回调中被捕获并吞噬:因此,实现所需功能的一种可能性是通过自定义契约解析器添加到JsonContract.OnSerializingCallbacks的人工回调中抛出异常异常,然后使用添加到JsonContract.OnErrorCallbacks的处理程序捕获并吞下异常。当与您正在执行的属性值过滤相结合时,此方法的优点是秘密对象无法序列化,即使它是根对象或包含在字典、动态对象或多维数组中也是如此。此方法不会干扰PreserveReferencesHandling.Arrays。执行此操作的一个统一解析程序如下:只读SerializationCallbackserializationCallback;只读SerializationErrorCallbackonErrorCallback;publicShouldSerializeContractResolver(PredicateshouldSerialize):base(){this.shouldSerialize=shouldSerialize;this.serializationCallback=(o,context)=>{if(shouldSerialize!=null&&!this.shouldSerialize(o))thrownewJsonSkipObjectException();};this.onErrorCallback=(o,context,errorContext)=>{if(errorContext.ErrorisJsonSkipObjectException){errorContext.Handled=true;}};}protectedoverrideJsonPropertyCreateProperty(MemberInfomember,MemberSerializationmemberSerialization){varproperty=base.CreateProperty(member,memberSerialization);if(shouldSerialize!=null){if(property.Readable){varoldShouldSerialize=property.ShouldSerialize;property.ShouldSerialize=(o)=>{if(oldShouldSerialize!=null&&!oldShouldSerialize(o))返回false;varvalue=property.ValueProvider.GetValue(o);如果(!this.shouldSerialize(value))返回false;返回真;};}}返回属性;}protectedoverrideJsonContractCreateContract(TypeobjectType){varcontract=base.CreateContract(objectType);contract.OnSerializingCallbacks.Add(serializationCallback);contract.OnErrorCallbacks.Add(onErrorCallback);退货合同;}}然后一个可能的用途是:publicinterfaceIConditionalSerialization{boolShouldSerialize();}publicclassConditionalSerializationObject:IConditionalSerialization{publicboolIsSecret{get;放;}publicstringSecretProperty{get{返回“不应该看到我”;}}//确保“正常”条件属性序列化没有被破坏publicboolShouldSerializeSecretProperty(){returnfalse;}#regionIConditionalSerialization成员boolIConditionalSerialization.ShouldSerialize(){返回!IsSecret;}#endregion}publicclassTestClass{publicstaticvoidTest(){Predicatefilter=(o)=>{varconditional=oasIConditionalSerialization;返回条件==null||条件.ShouldSerialize();};varsettings=newJsonSerializerSettings{ContractResolver=newShouldSerializeContractResolver(filter),};varok=newConditionalSerializationObject{IsSecret=false};varnotOk=newConditionalSerializationObject{IsSecret=true};测试(确定,设置);测试(新{Public=ok,Private=notOk},设置);测试(新[]{ok,notOk,ok,notOk},设置);测试(新[,]{{ok,notOk,ok,notOk}},设置);测试(新{Array=new[,]{{ok,notOk,ok,notOk}}},设置);尝试{测试(notOk,设置);}catch(Exceptionex){Console.WriteLine("抛出异常但未捕获序列化根对象"+notOk.GetType());控制台.WriteLine(ex);}}staticvoidTest(T值,JsonSerializerSettings设置){Console.WriteLine("Unfilteredobject:");Console.WriteLine(JToken.FromObject(value));varserializer=JsonSerializer.CreateDefault(设置);vartoken=JToken.FromObject(value,serializer);Console.WriteLine("筛选对象:");控制台.WriteLine(令牌);if(!token.SelectTokens("..IsSecret").All(t=>JToken.DeepEquals(t,(JValue)false))){thrownewInvalidOperationException("token.SelectTokens("..IsSecret").All(t=>JToken.DeepEquals(t,(JValue)true))");}if(token.SelectTokens("..SecretProperty").Any()){thrownewInvalidOperationException("token.SelectTokens("..SecretProperty").Any()");}Console.WriteLine("秘密对象和属性被成功过滤。");Console.WriteLine("");}}PrototypeFiddle请注意,抛出和捕获大量异常会影响性能。请参阅C#中的异常有多昂贵?.您需要分析您的Web应用程序以确定这是否是一个问题。您还需要确定Web服务在尝试序列化“秘密”根对象或执行其他操作时是否应返回异常。以上就是《JSON.Net自定义合约序列化与集合分享》C#学习教程的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢