Сериализация RestSharp для JSON, объект не использует атрибут SerializeAs, как ожидалось
Я использую RestSharp (версия 104.4 через NuGet) для совершения вызовов в веб-службу Rest. Я разработал набор объектов (POCO), который соответствует ресурсам, открытым в API. Однако имена свойств объектов не соответствуют ожидаемым службой Rest Rest при отправке данных, поэтому я хотел бы "преобразовать" их, когда я делаю запрос службе Rest, чтобы они соответствовали совпадению. Я прочитал, что добавление атрибута SerializeAs
(с указанным именем) в моем свойстве POCO сделает их сериализацией правильно, но это не будет.
Мой POCO
Imports RestSharp.Serializers
<Serializable(), SerializeAs(Name:="ApiMember")>
Public Class ApiMember
<SerializeAs(Name:="id")>
Public Property Id As Integer?
<SerializeAs(Name:="email")>
Public Property EmailAddress As String
<SerializeAs(Name:="firstname")>
Public Property Firstname As String
<SerializeAs(Name:="lastname")>
Public Property Lastname As String
End Class
Мой вызов API
Dim request As RestRequest = New RestRequest(Method.POST)
Dim member As ApiMember = new ApiMember()
member.EmailAddress = "[email protected]"
request.Resource = "members"
request.RequestFormat = DataFormat.Json
request.AddBody(member)
Dim client As RestClient = New RestClient()
client.BaseUrl = "http://url.com"
client.Authenticator = New HttpBasicAuthenticator("username", "password")
client.Execute(Of ApiGenericResponse)(request)
Что в конечном итоге выкладывается
{"Id":null,"EmailAddress":"[email protected]","Firstname":null,"Lastname":null}
Обратите внимание, что имя свойства не соответствует тикам, указанным в SerializeAs
(верхние регистры, имя EmailAddress)
Я что-то пропустил?
Ответы
Ответ 1
Это для @MaxiWheat и всех, кто интересуется тем, как использовать JSON.NET как сериализатор JSON в запросе RestSharp. В принципе, я использовал подход, описанный в в этом блоге Патриком Райли:
// create the request
var request = new RestRequest(yourUrlHere, Method.POST) { RequestFormat = DataFormat.Json };
// attach the JSON.NET serializer for RestSharp
restRequest.JsonSerializer = new RestSharpJsonNetSerializer();
а RestSharpJsonNetSerializer
- это реализация (менее 100 строк кода) из парней JSON.NET(John Sheehan), которые могут быть найдены на их Страницы Github
С этой настройкой мои проблемы ушли, и я смог иметь надлежащий DTO с хорошими свойствами CamelCase, а сериализованный JSON использует их во всех "строчных".
Ответ 2
Я столкнулся с этой проблемой и решил это немного иначе, чем выше, хотел бы отметить это здесь.
У нас есть класс factory
, который строит все наши запросы. Выглядит следующим образом
public IRestRequest CreatePutRequest<TBody>(string resource, TBody body)
{
var request = new RestRequest(resource)
{
Method = Method.PUT,
};
request.AddParameter("application/json", Serialize(body), ParameterType.RequestBody);
return request;
}
Вместо использования методов AddJsonBody
и AddBody
против запроса, оба из которых вызывают сериализацию, я использовал AddParameter
, который добавит объект, который вы передаете, без сериализации. Я создал метод под названием Serialise
, который использует JSON.net
для сериализации нашего класса.
private object Serialize<T>(T item)
{
return JsonConvert.SerializeObject(item);
}
Это позволяет нам использовать аннотацию JSON.net
JsonProperty
над вашими свойствами. Вот пример -
public class Example
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "created")]
public DateTime Created { get; set; }
[JsonProperty(PropertyName = "updated")]
public DateTime Updated { get; set; }
}
Ответ 3
В RestSharp 104.4 по умолчанию JsonSerializer
не использует атрибут [SerializeAs]
, как видно из исходного кода .
Обходной путь к этому заключается в создании настраиваемого сериализатора, который использует Json.NET JsonSerializer
(хороший пример здесь), а затем украсить ваши свойства с помощью [JsonProperty]
, например:
<JsonProperty("email")>
Public Property EmailAddress As String
Ответ 4
RestSharp использует SimpleJson. Эта библиотека не знает или не уважает атрибут [SerializeAs]
(который является XML-only в любом случае), он просто выводит имя свойства POCO, если он не скомпилирован с #SIMPLE_JSON_DATACONTRACT
, то вы можете использовать атрибут [DataContract]
для переименования свойств.
Таким образом, ваши варианты, похоже, состоят в том, чтобы перекомпилировать библиотеку SimpleJson с этим определением и украсить ваши свойства с помощью атрибута [DataContract(Name="lowercasepropertyname")]
или создать собственный сериализатор, который использует сериализатор JSON, который уважает другие атрибуты, как это предлагается в ответе @Ryan.
Ответ 5
Вы можете использовать следующий метод на стороне клиента. По сути, он использует десериализатор Newtonsoft вместо встроенного десериализатора RestSharp. Десериализатор Newtonsoft учитывает свойство DataMember Name или JsonProperty.
private T Execute<T>(RestRequest request)
{
var response = _client.Execute(request);
if (response.ErrorException != null)
throw new Exception("Error:" + response.ErrorException);
return (T)JsonConvert.DeserializeObject(response.Content, typeof(T));
}