Сериализация объекта запроса с использованием JSON
В настоящее время я работаю над доказательством концепции и столкнулся с проблемой, связанной с использованием JSON для сериализации HttpRequest.
Фон
Первоначально я думал, что смогу легко выполнить его, используя метод JSON.Encode(), как показано ниже:
JSON.Encode(HttpContext.Request)
Однако я быстро обнаружил, что это вызывает выбросы всех видов циклических ссылок (в первую очередь из-за фактической структуры и сложности объекта Request). Это происходит только при фактических встречах с свойствами, которые содержат циклическую ссылку, поскольку я ранее использовал следующий код для захвата только определенных элементов, которые мне нужны:
JSON.Encode(new {HttpContext.Request.Cookies,HttpContext.Request.Headers, ... });
который отлично работает.
Мне просто интересно, есть ли лучший способ справиться с этим (или лучший способ его обработки). Я подробно рассмотрю некоторые из подходов, которые я сделал до сих пор ниже, чтобы найти какие-либо области, в которых я, возможно, ошибся.
Предыдущие подходы
-
Использование Reflection для повторения каждого из свойств внутри
Запрос и попытка создания строки JSON
"Свойство по-недвижимости". (Это не удалось, когда встретились с круговым
ссылка)
-
Попытка сохранить каждое из свойств в объекте словаря, а затем использовать JSON для сериализации всего Словаря (в надежде, что он "сгладит" объект и упростит сериализацию)
-
Используя библиотеку JSON.NET и пытаясь сериализовать ее с помощью метода JsonConvert.SerializeObject() (я попытался пройти в нескольких дополнительных настройках, чтобы избежать круговой ссылки, но не повезло)
Мой последний подход (с использованием библиотеки JSON.NET), я думал, приблизился бы к работе, однако я столкнулся с ошибкой, которая включала свойство "Тайм-аут" для объектов Stream в запросе.
Я не против просто избегать сериализации объектов Stream и Circular References. Я просто пытаюсь захватить как можно больше объекта Request, избегая любого из этих типов неудач.
Ответы
Ответ 1
Любая конкретная причина, по которой вы не используете JSON.Net? У него есть параметр, называемый PreserveReferencesHandling
, который тегирует объекты с дополнительным свойством ( "$ id": "##" ). Если этот объект появляется в сериализации более одного раза, вместо записи объекта он заменяет его "$ ref": "##", указывающий на уже существующий json для объекта. Это обходит круговую привязку.
Я никогда не пробовал возвращать JSON в этом формате к вызову $.ajax, поэтому я не знаю, что будет участвовать в его синтаксическом разборе.
Ответ 2
Я использовал JsonConvert.SerializeObject
в своем проекте, и он работает нормально. Кажется, это может решить вашу проблему.
JsonConvert.SerializeObject(reqObject)
Ответ 3
Я просто попытался сделать то же самое, теперь мне удалось получить что-то сериализующееся с помощью 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, где я есть, так что в моем списке игнорируемых свойств - очевидно, удалите это, если вы можете включить его!