Сериализация объекта запроса с использованием 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, где я есть, так что в моем списке игнорируемых свойств - очевидно, удалите это, если вы можете включить его!