Итак, у меня есть такой метод:
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);
Так что да, можем ли мы получить лучший сериализатор по умолчанию, способ переопределить сериализатор или более элегантный метод для установки строки в качестве тела?
Есть планы вернуться или хотя бы предложить библиотеку Json.Net для де / сериализации. Однако есть некоторые проблемы, над которыми я все еще работаю. Тем не менее, вы можете реализовать собственный де / сериализатор, который будет его использовать. Я также посмотрю, что я могу сделать с реализацией словарей SimpleJson.
Я тоже столкнулся с этой проблемой и нашел обходной путь, который сейчас соответствует моим потребностям.
Я использовал метод расширения для словаря, описанный здесь: http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
ExpandoObject eo = mydictionary.ToExpando ();
Это преобразует словарь
Затем 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
{
///
/// Ключ, содержащий динамические данные.
///
общедоступный словарь
новый словарь
/// <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
Самый полезный комментарий
Я решил проблему, напрямую манипулируя параметром body: