【问题标题】:Serializing a Request Object using JSON使用 JSON 序列化请求对象
【发布时间】:2023-03-29 16:15:01
【问题描述】:

我目前正在进行概念验证,遇到了一个涉及使用 JSON 序列化 HttpRequest 的问题。

背景

我最初认为我可以使用JSON.Encode() 方法轻松完成它,如下所示:

JSON.Encode(HttpContext.Request)

但是,我很快发现这会导致抛出各种循环引用(主要是由于 Request 对象的实际结构和复杂性)。这些仅在实际遇到包含循环引用的属性时才会发生,因为我之前使用以下代码来获取我需要的特定元素:

JSON.Encode(new {HttpContext.Request.Cookies,HttpContext.Request.Headers, ... });

效果很好。

我只是好奇是否有更好的处理方法(或者最好的处理方法是什么)。我将在下面详细介绍到目前为止我所采取的一些方法,以找出我可能出错的任何地方。

以前的方法

  • 使用反射遍历 请求并尝试构造一个 JSON 字符串 “逐个属性”。 (遇到循环时失败 参考)

  • 尝试将每个属性存储在 Dictionary 对象中,然后使用 JSON 序列化整个 Dictionary(希望它将“扁平化”对象并使其更容易序列化)

  • 使用 JSON.NET library 并尝试通过 JsonConvert.SerializeObject() 方法对其进行序列化(我已尝试传递几个额外的设置以避免循环引用,但没有任何运气)

我认为我的最新方法(使用 JSON.NET 库)可以接近工作,但是我遇到了一个错误,涉及请求中 Stream 对象的“超时”属性。 p>

我并不反对简单地避免序列化 Stream 对象和循环引用。我只是想尽可能多地获取 Request 对象,同时避免任何这些类型的事故。

【问题讨论】:

    标签: c# asp.net-mvc json serialization


    【解决方案1】:

    我只是尝试做同样的事情,我现在已经设法使用带有合同解析器的 JsonConvert 进行序列化以忽略所有问题属性 - 我使用这一行来进行序列化:

    string reqStr = JsonConvert.SerializeObject(context.Request,
        Formatting.Indented, new JsonSerializerSettings {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            ContractResolver = new IgnoreErrorPropertiesResolver()
    });
    

    这是我使用的合约解析器代码:

    public class IgnoreErrorPropertiesResolver : DefaultContractResolver
    {
    
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
    
            if (["InputStream",
                "Filter",
                "Length",
                "Position",
                "ReadTimeout",
                "WriteTimeout",
                "LastActivityDate",
                "LastUpdatedDate",
                "Session"
            ].Contains(property.PropertyName)) {
                property.Ignored = true;
            }
            return property;
        }
    }
    

    这将需要 Newtonsoft.Json.SerializationSystem.Reflection 使用。

    碰巧我不能在我所在的位置包含 Session 对象,所以它在我的忽略属性列表中 - 如果可以包含它,显然删除它!

    【讨论】:

    • 此解决方案有效,但如果通过添加另一个无法序列化的属性来更改请求对象架构,它可能会失败。如果将 JsonSerializerSettings 上的 Error 属性设置为将 ErrorEventArgs 上的 ErrorContext.Handled 属性设置为 true 的方法,则将处理(或应该处理)未来的架构更改。
    【解决方案2】:

    您不使用 JSON.Net 的任何特殊原因?它有一个名为PreserveReferencesHandling 的设置,它使用附加属性(“$id”:“##”)标记对象。如果该对象多次出现在序列化中,而不是再次写入该对象,而是将其替换为“$ref”:“##”,指向该对象已经存在的 json。这绕过了循环引用。

    我从未尝试将这种格式的 JSON 返回到 $.ajax 调用,所以我不知道在 web 端解析它会涉及什么。

    【讨论】:

    • 感谢马尔科姆的建议。自从阅读了您的建议并应用了几个设置后,我尝试了几种不同的方式使用它,但我仍然遇到似乎(主要与 Streams 相关?)“此流不支持流”的问题。有什么想法吗?
    • 这让我觉得你不能 JSON 转换具有流属性的对象。
    • 我也开始倾向于这种方式。序列化 Stream 时似乎会导致超时,然后输出前面提到的答案。我想我必须想办法忽略流/循环引用。
    【解决方案3】:

    我在我的项目中使用了JsonConvert.SerializeObject,它运行良好。看来它可以解决你的问题。

    JsonConvert.SerializeObject(reqObject)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-15
      相关资源
      最近更新 更多