Restsharp: Сериализатор JSON не превращает словарь C # в объект JSON, как ожидалось

Созданный на 27 мая 2015  ·  6Комментарии  ·  Источник: restsharp/RestSharp

Итак, у меня есть такой метод:

public static void SomeApiCall(string foo, string bar, Dictionary<String, Dictionary<String, int[]>> list, ...)
{
  var request = new RestRequest("some/endpoint", Method.PUT);
  request.AddJsonBody(new { foo = foo, bar = bar, list = list });
  ...
}

Обратите внимание, что тип list - это словарь. Это должно быть напрямую переведено в JSON как объект типа {"key1": ..., "key2": ...} , но то, что я получаю на другом конце, на самом деле [{"Key":"key1","Value": ...}, {"Key":"key2","Value": ...}] , что, конечно, несовместимо с тем, что отправляют другие клиенты. Словари внутри него имеют ту же проблему.

Насколько я могу судить, RestSharp использует SimpleJson в качестве сериализатора. Я попытался сериализовать с помощью Newtonsoft, который выдает ожидаемую строку JSON. Он отлично работает после того, как нашел хакерский метод для отправки строки в теле, что, по-видимому, является единственным способом не сериализовать тело с помощью RestSharp внутренне:

var jout = JObject.FromObject(new { foo = foo, bar = bar, list = list });
request.AddParameter("application/json; charset=utf-8", jout.ToString(Formatting.None), ParameterType.RequestBody);

Так что да, можем ли мы получить лучший сериализатор по умолчанию, способ переопределить сериализатор или более элегантный метод для установки строки в качестве тела?

feature-request

Самый полезный комментарий

Я решил проблему, напрямую манипулируя параметром body:

restRequest.AddJsonBody(toBeSerializedContainingDictionary);
var bodyParameter = restRequest.Parameters.First(p => p.Type == ParameterType.RequestBody);
restRequest.Parameters.Remove(bodyParameter);
bodyParameter.Value = JsonConvert.SerializeObject(toBeSerializedContainingDictionary);
restRequest.Parameters.Add(bodyParameter);

Все 6 Комментарий

Есть планы вернуться или хотя бы предложить библиотеку Json.Net для де / сериализации. Однако есть некоторые проблемы, над которыми я все еще работаю. Тем не менее, вы можете реализовать собственный де / сериализатор, который будет его использовать. Я также посмотрю, что я могу сделать с реализацией словарей SimpleJson.

Я тоже столкнулся с этой проблемой и нашел обходной путь, который сейчас соответствует моим потребностям.

Я использовал метод расширения для словаря, описанный здесь: http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/

ExpandoObject eo = mydictionary.ToExpando ();

Это преобразует словарьв (динамический) ExpandoObject.
Затем ExpandoObject правильно сериализуется в формате: {"key1": ..., "key2": ...}

В моем случае у меня был словарь> поэтому мне пришлось сначала преобразовать его в словарь

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

Я решил проблему, напрямую манипулируя параметром body:

restRequest.AddJsonBody(toBeSerializedContainingDictionary);
var bodyParameter = restRequest.Parameters.First(p => p.Type == ParameterType.RequestBody);
restRequest.Parameters.Remove(bodyParameter);
bodyParameter.Value = JsonConvert.SerializeObject(toBeSerializedContainingDictionary);
restRequest.Parameters.Add(bodyParameter);

@mathume Спасибо ... вот в

Другой обходной путь - создать ISerializer чтобы справиться с этим. Вы можете сделать его достаточно универсальным, чтобы поддерживать произвольный DTO.

`` С #
///


/// Пример DTO, где у нас есть ключ верхнего уровня, значение которого является объектом JSON
/// с динамическими ключами. Значением этих ключей является какой-то объект.
///

открытый класс MyDto
{
///
/// Ключ, содержащий динамические данные.
///

общедоступный словарьSomeKey {получить; установленный; знак равно
новый словарь();

/// <summary>
/// Helper method to easily add new objects.
/// </summary>
public MyDto AddDynamicObject(string dynamicKey, object obj)
{
    SomeKey[dynamicKey] = obj;
    return this;
}

}

///


/// Сериализатор, используемый для создания строк JSON из DTO.
///

открытый класс MyDtoSerializer: ISerializer
{
общедоступная строка RootElement {получить; установленный; }
общедоступная строка Namespace {получить; установленный; }
общедоступная строка DateFormat {получить; установленный; }
общедоступная строка ContentType {получить; установленный; }

/// <summary>
/// Serialize the object, where obj is assumed to be a MyDto instance.
/// </summary>
public string Serialize(object obj)
{
    return JsonConvert.SerializeObject(obj);
}

}

///


/// Простое расширение, показывающее, как добавить данные в запрос.
///

общедоступный статический IRestRequest AddMyDto (IRestRequest restRequest, MyDto dto)
{
// Изменяем сериализатор, чтобы использовать наш новый сериализатор
// Обратите внимание, что вам может потребоваться установить ContentType сериализатора как «application / json»
request.JsonSerializer = новый MyDtoSerializer ();

// Add the DTO - behind the scenes it is serialized to a JSON string using our serializer
request.AddJsonBody(dto);
return request;

}

The output JSON will then look something like the following (note - the values are simply placeholders):

```JSON
{
    "SomeKey": {
        "dynamicKey-1": "value-1",
        "dynamicKey-2": "value-2",
        "dyanmicKey-n": "value-n"
    }
}

Это будет обработано как часть # 1018

Была ли эта страница полезной?
0 / 5 - 0 рейтинги