Подтвердить что ты не робот

Сериализация 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)

Я что-то пропустил?

4b9b3361

Ответ 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));
    }