• <small id='QOWi8'></small><noframes id='QOWi8'>

    • <bdo id='QOWi8'></bdo><ul id='QOWi8'></ul>

    <legend id='QOWi8'><style id='QOWi8'><dir id='QOWi8'><q id='QOWi8'></q></dir></style></legend>
    <i id='QOWi8'><tr id='QOWi8'><dt id='QOWi8'><q id='QOWi8'><span id='QOWi8'><b id='QOWi8'><form id='QOWi8'><ins id='QOWi8'></ins><ul id='QOWi8'></ul><sub id='QOWi8'></sub></form><legend id='QOWi8'></legend><bdo id='QOWi8'><pre id='QOWi8'><center id='QOWi8'></center></pre></bdo></b><th id='QOWi8'></th></span></q></dt></tr></i><div id='QOWi8'><tfoot id='QOWi8'></tfoot><dl id='QOWi8'><fieldset id='QOWi8'></fieldset></dl></div>
    1. <tfoot id='QOWi8'></tfoot>

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

        JSON.Net custom contract serialization and Collections(JSON.Net 自定义合约序列化和集合)
          <tbody id='DOZ3s'></tbody>

              <i id='DOZ3s'><tr id='DOZ3s'><dt id='DOZ3s'><q id='DOZ3s'><span id='DOZ3s'><b id='DOZ3s'><form id='DOZ3s'><ins id='DOZ3s'></ins><ul id='DOZ3s'></ul><sub id='DOZ3s'></sub></form><legend id='DOZ3s'></legend><bdo id='DOZ3s'><pre id='DOZ3s'><center id='DOZ3s'></center></pre></bdo></b><th id='DOZ3s'></th></span></q></dt></tr></i><div id='DOZ3s'><tfoot id='DOZ3s'></tfoot><dl id='DOZ3s'><fieldset id='DOZ3s'></fieldset></dl></div>
              <legend id='DOZ3s'><style id='DOZ3s'><dir id='DOZ3s'><q id='DOZ3s'></q></dir></style></legend><tfoot id='DOZ3s'></tfoot>
              • <bdo id='DOZ3s'></bdo><ul id='DOZ3s'></ul>
                • <small id='DOZ3s'></small><noframes id='DOZ3s'>

                  本文介绍了JSON.Net 自定义合约序列化和集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  限时送ChatGPT账号..

                  我正在尝试创建一个 IContractResolver 来简化我对 WebApi 项目的安全处理.

                  I am attempting to create a IContractResolver to simplify my security handling on a WebApi Project.

                  我正在尝试什么:

                  我想根据一组动态条件(例如调用端点的用户的角色)序列化某些对象/属性.

                  I want to serialize certain objects/properties based on a set of dynamic conditions ( for examples the Role of the user that called the endpoint).

                  所以我实现了一个在接口的 CreateProperty 覆盖中检查的自定义属性,并将 ShouldSerialize 函数设置为我自己的逻辑.

                  So I implemented a custom attribute that is checked in the CreateProperty override of the Interface, and set the ShouldSerialize function to my own logic.

                  我现在的问题是,是否可以有条件地序列化某个列表中的完整对象?而不是在预处理步骤中过滤列表(如果我更改对象,这很容易出错),我希望它由当前的 ContractResolver 递归处理.

                  My question now is, is it possible to conditionally serialize full objects that are in a certain list ? Instead of filtering the lists in a preprocessing step (which is error prone, if I change my objects) I would like it to be handled recursively by the current ContractResolver.

                  在某种程度上,我试图得到这样的东西:

                  In a way I was trying to get something like this:

                  override void CreateObject(JSONObject ob){
                  if ( ob.DeclaringType == MyType)
                  {
                     ob.ShouldSerialize = instance => {[...] }; //Custom Logic
                  }
                  }
                  

                  我错过了覆盖,这根本不可能吗?有没有更好的方法来实际执行此操作,而不必预解析"我的所有值?

                  Am I missing a override, is this not possible at all? Is there a better way to actually do this, without me having to "pre-parse" all my values?

                  推荐答案

                  这不是开箱即用的.如果您检查 JsonSerializerInternalWriter.SerializeList() 你会看到没有逻辑可以跳过基于某些过滤器的集合条目.

                  This is not implemented out of the box. If you inspect the source for JsonSerializerInternalWriter.SerializeList() you will see there is no logic to skip collection entries based on some filter.

                  但是,Json.NET 确实具有强大的异常处理.如果在开始序列化对象时抛出异常,然后在 [OnError] 回调:

                  However, Json.NET does have robust exception handling. If an exception is thrown when beginning to serialize an object then caught and swallowed in an [OnError] callback:

                  • 如果写入数组条目,则数组条目将被跳过(您想要的行为).
                  • 如果写入根对象,异常不会被捕获(可能是一个错误?)
                  • 否则写入null.
                  • If writing an array entry, the array entry is skipped (your desired behavior).
                  • If writing the root object, the exception is not caught (possibly a bug?)
                  • Otherwise null is written.

                  因此,实现所需功能的一种可能性是从添加到 JsonContract.OnSerializingCallbacks 由您的自定义合同解析器,然后使用添加到 JsonContract.OnErrorCallbacks.当与您已经在做的对属性值进行过滤结合使用时,这种方法的优点是保证即使它是根对象或包含在字典、动态对象或多维数组中的秘密对象也不能被序列化.这种方法不会干扰 PreserveReferencesHandling.Arrays.

                  Thus one possibility to achieve your desired functionality would be to throw an exception from an artificial callback added to JsonContract.OnSerializingCallbacks by your custom contract resolver, then catch and swallow the exception with a handler added to JsonContract.OnErrorCallbacks. When combined with filtering on property values as you are already doing, this approach has the advantage of guaranteeing a secret object cannot be serialized even when it is the root object or when contained in a dictionary, a dynamic object, or a multidimensional array. This approach will not interfere with PreserveReferencesHandling.Arrays.

                  执行此操作的一个合同解析器如下:

                  One contract resolver that does this is as follows:

                  sealed class JsonSkipObjectException : JsonException
                  {
                  }
                  
                  public class ShouldSerializeContractResolver : DefaultContractResolver
                  {
                      readonly Predicate<object> shouldSerialize;
                      readonly SerializationCallback serializationCallback;
                      readonly SerializationErrorCallback onErrorCallback;
                  
                      public ShouldSerializeContractResolver(Predicate<object> shouldSerialize)
                          : base()
                      {
                          this.shouldSerialize = shouldSerialize;
                          this.serializationCallback = (o, context) =>
                              {
                                  if (shouldSerialize != null && !this.shouldSerialize(o))
                                      throw new JsonSkipObjectException();
                              };
                          this.onErrorCallback = (o, context, errorContext) =>
                              {
                                  if (errorContext.Error is JsonSkipObjectException)
                                  {
                                      errorContext.Handled = true;
                                  }
                              };
                      }
                  
                      protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
                      {
                          var property = base.CreateProperty(member, memberSerialization);
                  
                          if (shouldSerialize != null)
                          {
                              if (property.Readable)
                              {
                                  var oldShouldSerialize = property.ShouldSerialize;
                                  property.ShouldSerialize = (o) =>
                                      {
                                          if (oldShouldSerialize != null && !oldShouldSerialize(o))
                                              return false;
                                          var value = property.ValueProvider.GetValue(o);
                                          if (!this.shouldSerialize(value))
                                              return false;
                                          return true;
                                      };
                              }
                          }
                          return property;
                      }
                  
                      protected override JsonContract CreateContract(Type objectType)
                      {
                          var contract = base.CreateContract(objectType);
                          contract.OnSerializingCallbacks.Add(serializationCallback);
                          contract.OnErrorCallbacks.Add(onErrorCallback);
                          return contract;
                      }
                  }
                  

                  那么一种可能的用途是:

                  Then one possible use would be:

                  public interface IConditionalSerialization
                  {
                      bool ShouldSerialize();
                  }
                  
                  public class ConditionalSerializationObject : IConditionalSerialization
                  {
                      public bool IsSecret { get; set; }
                  
                      public string SecretProperty { get { return "should not see me"; } }
                  
                      // Ensure "normal" conditional property serialization is not broken
                      public bool ShouldSerializeSecretProperty()
                      {
                          return false;
                      }
                  
                      #region IConditionalSerialization Members
                  
                      bool IConditionalSerialization.ShouldSerialize()
                      {
                          return !IsSecret;
                      }
                  
                      #endregion
                  }
                  
                  public class TestClass
                  {
                      public static void Test()
                      {
                          Predicate<object> filter = (o) => 
                              {
                                  var conditional = o as IConditionalSerialization;
                                  return conditional == null || conditional.ShouldSerialize();
                              };
                          var settings = new JsonSerializerSettings
                          {
                              ContractResolver = new ShouldSerializeContractResolver(filter),
                          };
                  
                          var ok = new ConditionalSerializationObject { IsSecret = false };
                          var notOk = new ConditionalSerializationObject { IsSecret = true };
                  
                          Test(ok, settings);
                          Test(new { Public = ok, Private = notOk }, settings);
                          Test(new [] { ok, notOk, ok, notOk }, settings);
                          Test(new[,] {{ ok, notOk, ok, notOk }}, settings);
                          Test(new { Array = new[,] { { ok, notOk, ok, notOk } } }, settings);
                          try
                          {
                              Test(notOk, settings);
                          }
                          catch (Exception ex)
                          {
                              Console.WriteLine("Exception thrown and not caught serializing root object " + notOk.GetType());
                              Console.WriteLine(ex);
                          }
                      }
                  
                      static void Test<T>(T value, JsonSerializerSettings settings)
                      {
                          Console.WriteLine("Unfiltered object: ");
                          Console.WriteLine(JToken.FromObject(value));
                  
                          var serializer = JsonSerializer.CreateDefault(settings);
                          var token = JToken.FromObject(value, serializer);
                          Console.WriteLine("Filtered object: ");
                          Console.WriteLine(token);
                          if (!token.SelectTokens("..IsSecret").All(t => JToken.DeepEquals(t, (JValue)false)))
                          {
                              throw new InvalidOperationException("token.SelectTokens("..IsSecret").All(t => JToken.DeepEquals(t, (JValue)true))");
                          }
                          if (token.SelectTokens("..SecretProperty").Any())
                          {
                              throw new InvalidOperationException("token.SelectTokens("..SecretProperty").Any()");
                          }
                          Console.WriteLine("Secret objects and properties were successfully filtered.");
                          Console.WriteLine("");
                      }
                  }
                  

                  原型小提琴.

                  请注意,抛出和捕获大量异常可能会对性能产生影响.请参阅 C# 中的异常有多昂贵?.您将需要分析您的 Web 应用程序以确定这是否是一个问题.您还需要决定您的 Web 服务在尝试序列化秘密"根对象时是否应该返回异常,或者执行其他操作.

                  Note that throwing and catching a large number of exceptions can have performance implications. See How expensive are exceptions in C#?. You will need to profile your web application to determine whether this is a problem. You also will need to decide whether your web service should return an exception when attempting to serialize a "secret" root object, or do something different.

                  这篇关于JSON.Net 自定义合约序列化和集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  Force JsonConvert.SerializeXmlNode to serialize node value as an Integer or a Boolean(强制 JsonConvert.SerializeXmlNode 将节点值序列化为整数或布尔值)
                  Using JSON to Serialize/Deserialize TimeSpan(使用 JSON 序列化/反序列化 TimeSpan)
                  Could not determine JSON object type for type quot;Classquot;(无法确定类型“Class的 JSON 对象类型.)
                  How to deserialize a JSONP response (preferably with JsonTextReader and not a string)?(如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?)
                  how to de-serialize JSON data in which Timestamp it-self contains fields?(如何反序列化时间戳本身包含字段的JSON数据?)
                  c# JSON Serialization Use Value Instead of Property Name(c# JSON序列化使用值而不是属性名)
                    <tbody id='j7Lr7'></tbody>

                  1. <small id='j7Lr7'></small><noframes id='j7Lr7'>

                  2. <i id='j7Lr7'><tr id='j7Lr7'><dt id='j7Lr7'><q id='j7Lr7'><span id='j7Lr7'><b id='j7Lr7'><form id='j7Lr7'><ins id='j7Lr7'></ins><ul id='j7Lr7'></ul><sub id='j7Lr7'></sub></form><legend id='j7Lr7'></legend><bdo id='j7Lr7'><pre id='j7Lr7'><center id='j7Lr7'></center></pre></bdo></b><th id='j7Lr7'></th></span></q></dt></tr></i><div id='j7Lr7'><tfoot id='j7Lr7'></tfoot><dl id='j7Lr7'><fieldset id='j7Lr7'></fieldset></dl></div>
                            <bdo id='j7Lr7'></bdo><ul id='j7Lr7'></ul>
                            <tfoot id='j7Lr7'></tfoot>
                            <legend id='j7Lr7'><style id='j7Lr7'><dir id='j7Lr7'><q id='j7Lr7'></q></dir></style></legend>