问题 使用JSON序列化请求对象


我目前正致力于概念验证,并遇到了一个涉及使用JSON序列化HttpRequest的问题。

背景

我原本以为我能够轻松地完成它 JSON.Encode() 方法如下:

JSON.Encode(HttpContext.Request)

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

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

哪个工作得很好。

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

以前的方法

  • 使用Reflection迭代遍历的每个属性 请求并尝试构造JSON字符串 “财产的属性”。 (遇到圆形时失败了 参考

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

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

我的最新方法(使用JSON.NET库)我认为会接近工作,但是我遇到了一个错误,该错误涉及Request中Stream对象的“Timeout”属性。

我并不反对简单地避免序列化Stream对象和循环引用。我只是试图抓住尽可能多的Request对象,同时避免任何这些类型的意外。


7282
2018-04-02 03:38


起源



答案:


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

我从未尝试将该格式的JSON返回到$ .ajax调用,因此我不知道在Web端解析它将涉及什么。


4
2018-04-02 04:36



感谢Malcolm的建议。我已经尝试过几种不同的方式,因为阅读你的建议和应用几个设置,但我仍然遇到问题(主要与Streams有关?)“此流不支持流”。有任何想法吗? - Rion Williams
这让我觉得你不能JSON转换一个具有流属性的对象。 - Malcolm O'Hare
我也开始倾向于这种方式。在序列化Stream时它似乎会导致超时,然后它会输出前面提到的答案。我想我必须想办法忽略Streams / Circular References。 - Rion Williams


答案:


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

我从未尝试将该格式的JSON返回到$ .ajax调用,因此我不知道在Web端解析它将涉及什么。


4
2018-04-02 04:36



感谢Malcolm的建议。我已经尝试过几种不同的方式,因为阅读你的建议和应用几个设置,但我仍然遇到问题(主要与Streams有关?)“此流不支持流”。有任何想法吗? - Rion Williams
这让我觉得你不能JSON转换一个具有流属性的对象。 - Malcolm O'Hare
我也开始倾向于这种方式。在序列化Stream时它似乎会导致超时,然后它会输出前面提到的答案。我想我必须想办法忽略Streams / Circular References。 - Rion Williams


我只是尝试做同样的事情,我现在设法使用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.Serialization 和 System.Reflection usings。

碰巧我不能包括 Session对象我在哪里,所以在我的被忽略的属性列表中 - 显然删除它,如果你可以包括它!


4
2018-01-25 13:00





我用过 JsonConvert.SerializeObject 在我的项目中,它工作正常。它似乎可以解决你的问题。

JsonConvert.SerializeObject(reqObject)

3
2017-10-21 20:31