我目前正致力于概念验证,并遇到了一个涉及使用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 library并尝试通过JsonConvert.SerializeObject()方法序列化它(我试图传递几个额外的设置以避免循环引用,但还没有运气)
我的最新方法(使用JSON.NET库)我认为接近工作,但是我遇到了一个错误,该错误涉及请求中Stream对象的“超时”属性。
我并不反对简单地避免序列化Stream对象和循环引用。我只想尽可能多地抓取Request对象,同时避免任何类型的意外事件。
答案 0 :(得分:6)
我只是尝试做同样的事情,我现在设法使用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
使用。
碰巧我无法将Session
对象包含在我所在的位置,以便在我的已忽略属性列表中显示 - 如果可以包含它,请明确删除它!
答案 1 :(得分:4)
您没有使用JSON.Net的任何特殊原因?它有一个名为PreserveReferencesHandling
的设置,用于标记具有附加属性的对象(" $ id":" ##")。如果该对象不止一次出现在序列化中,而不是再次写入该对象,则将其替换为" $ ref":" ##"指向对象的已存在的json。这避免了循环引用。
我从未尝试将该格式的JSON返回到$ .ajax调用,因此我不知道在网络端解析它会涉及到什么。
答案 2 :(得分:3)
我在我的项目中使用了JsonConvert.SerializeObject
并且工作正常。它似乎可以解决你的问题。
JsonConvert.SerializeObject(reqObject)