Как заставить RestSharp использовать BSON?

Я использую RestSharp и Json.NET для сериализации (см. здесь).

Json.NET поддерживает BSON, и, поскольку некоторые из моих запросов содержат огромные блоки двоичных данных, я думаю, что это значительно ускорит мое приложение. Однако, насколько я могу судить, RestSharp не имеет встроенной поддержки BSON.

Использование Json.NET реализовано как пользовательский сериализатор для RestSharp, поэтому на первый взгляд кажется, что можно изменить этот пользовательский сериализатор для использования BSON. Но метод Serialize интерфейса RestSharp.Serializers.ISerializer возвращает string, что (я предполагаю) не подходит для BSON. Итак, я предполагаю, что для реализации этого изменения в RestSharp потребуются более значительные изменения.

Кто-нибудь нашел способ сделать это?


Обновление: я просмотрел источник RestSharp и обнаружил, что метод RestRequest.AddBody, который берет мой объект и сериализует его в тело запроса, в конечном итоге вызывает Request.AddParameter (с сериализованными данными объекта и типом параметра RequestBody).

Я подумал, что смогу сериализовать свой объект в BSON, а затем напрямую вызвать Request.AddParameter — и действительно могу. Однако когда RestSharp затем выполняет RestRequest, ему не удается поместить двоичное содержимое в запрос, поскольку существуют другие встроенные предположения о том, что содержимое запроса закодировано в UTF-8.

Таким образом, похоже, что этот хак не сработает - нужно будет внести некоторые изменения в сам RestSharp, а я не человек для этой работы...


Обновление 2: я решил попробовать использовать отладчик, чтобы выяснить, сколько RestSharp мне придется изменить, чтобы решить проблему с кодировкой тела, поэтому я заменил свою версию NuGet RestSharp и включил проект RestSharp в свой решение. И... это сработало.

Оказывается, за последние несколько месяцев в RestSharp произошли изменения, которых еще нет в версии NuGet.

Таким образом, теперь вы можете использовать AddParameter и передавать уже закодированный в BSON объект, а RestSharp без проблем отправит его на сервер.


person Gary McGill    schedule 21.08.2013    source источник


Ответы (2)


Согласно обновлениям в моем вопросе, получается, что если у вас есть последний источник RestSharp, то вместо этого:

        request.AddBody(myObject);

... вы можете сделать это вместо этого всякий раз, когда у вас есть полезная нагрузка, которая выиграет от использования BSON:

        using (var memoryStream = new System.IO.MemoryStream())
        {
            using (var bsonWriter = new Newtonsoft.Json.Bson.BsonWriter(memoryStream))
            {
                var serializer = new Newtonsoft.Json.JsonSerializer();

                serializer.Serialize(bsonWriter, myObject);

                var bytes = memoryStream.ToArray();

                request.AddParameter("application/bson", bytes, RestSharp.ParameterType.RequestBody);
            }
        }

Обратите внимание, что первый параметр для AddParameter предположительно является именем параметра, но в случае ParameterType.RequestBody он фактически используется как тип контента. (Юк).

Обратите внимание, что это зависит от изменения, внесенного в RestSharp 11 апреля 2013 г. пользователем ewanmellor/ayoung, и это изменение < em>нет в текущей версии NuGet (104.1). Следовательно, это будет работать, только если вы включите текущий источник RestSharp в свой проект.

person Gary McGill    schedule 22.08.2013

Ответ Гэри на его собственный вопрос был невероятно полезен для сериализации спокойных звонков. Я хотел ответить, как десериализовать спокойные вызовы с помощью JSON.NET. Я использую RestSharp версии 104.4 для Silverlight. Мой сервер использует Web API 2.1 с включенной поддержкой BSON.

Чтобы принять ответ BSON, создайте десериализатор BSON для RestSharp следующим образом.

public class BsonDeserializer : IDeserializer
{
    public string RootElement { get; set; }
    public string Namespace { get; set; }
    public string DateFormat { get; set; }

    public T Deserialize<T>(IRestResponse response)
    {
        using (var memoryStream = new MemoryStream(response.RawBytes))
        {
            using (var bsonReader = new BsonReader(memoryStream))
            {
                var serializer = new JsonSerializer();
                return serializer.Deserialize<T>(bsonReader);
            }
        }
    }
}

Затем убедитесь, что ваш запрос принимает "application/bson"

var request = new RestRequest(apiUrl, verb);
request.AddHeader("Accept", "application/bson");

И добавьте обработчик для этого типа носителя

var client = new RestClient(url);
client.AddHandler("application/bson", new BsonDeserializer());
person Onosa    schedule 27.10.2014
comment
Этот ответ мне очень помог, если кто-то получает исключение. Последовательность содержит более одного элемента при добавлении обработчика, я исправил это, добавив обработчики перед добавлением заголовков по умолчанию в экземпляр RestClient. - person yvesmancera; 26.10.2017