.net RestSharp 序列化为 JSON,对象未按预期使用 SerializeAs 属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21633649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:38:16  来源:igfitidea点击:

RestSharp serialization to JSON, object is not using SerializeAs attribute as expected

.netjsonvb.netrestrestsharp

提问by MaxiWheat

I am using RestSharp(version 104.4 via NuGet) to make calls to a Rest Web Service. I have designed a set of objects (POCO) which matches resources exposed in the API. However, my objects property names does not match those expected by the Rest Service when posting data, so I would like to "transform" them when I make a request to the Rest service to make them match match. I read that adding SerializeAsattribute (with a Name specified) on my POCO's property will make them serialize correctly, but it won't.

我正在使用RestSharp(通过 NuGet 版本 104.4)来调用 Rest Web 服务。我设计了一组与 API 中公开的资源相匹配的对象 (POCO)。但是,我的对象属性名称在发布数据时与 Rest 服务预期的名称不匹配,因此当我向 Rest 服务发出请求以使它们匹配时,我想“转换”它们。我读到SerializeAs在我的 POCO 的属性上添加属性(指定名称)将使它们正确序列化,但不会。

My 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

My Call to the API

我对 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)

What ends up being posted

什么最终被发布

{"Id":null,"EmailAddress":"[email protected]","Firstname":null,"Lastname":null}

Notice the name of the properties does not match thoses I specified in SerializeAs(uppercases, name of EmailAddress)

请注意,属性名称与我在SerializeAs(大写,电子邮件地址名称)中指定的名称不匹配

Am I missing something ?

我错过了什么吗?

回答by marc_s

This is for @MaxiWheat and anyone else interested in how to use JSON.NETas the JSON serializer in a RestSharp request. Basically, I used the approach described in this blog post by Patrick Riley:

这适用于@MaxiWheat 和其他任何对如何在 RestSharp 请求中使用JSON.NET作为 JSON 序列化程序感兴趣的人。基本上,我使用了Patrick Riley这篇博文中描述的方法:

// create the request
var request = new RestRequest(yourUrlHere, Method.POST) { RequestFormat = DataFormat.Json };

// attach the JSON.NET serializer for RestSharp
restRequest.JsonSerializer = new RestSharpJsonNetSerializer();

and the RestSharpJsonNetSerializeris an implementation (less than 100 lines of code) from the JSON.NET guys (John Sheehan) that can be found on their Github pages

RestSharpJsonNetSerializer是来自 JSON.NET 人员 (John Sheehan) 的实现(少于 100 行代码),可以在他们的 Github 页面上找到

With this setup, my problems went away and I was able to have a proper DTO with nice CamelCase properties, while the serialized JSON uses them in all "lowercase".

有了这个设置,我的问题就消失了,我能够拥有一个带有漂亮 CamelCase 属性的正确 DTO,而序列化的 JSON 使用它们全部“小写”。

回答by Opster Elasticsearch - Nathan

I came across this issue, and solved this a slightly different way than above, wanted to note it here.

我遇到了这个问题,并以与上面略有不同的方式解决了这个问题,想在这里记录一下。

We have a factoryclass that builds all of our requests. Looks like the following

我们有一个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;
}

Rather than use the AddJsonBodyand AddBodymethods against the request, both of which cause serialisation, I used AddParameterwhich will add the object you pass in without serialisation. I created a method called Serialise, which uses JSON.netto serialise our class.

而不是针对请求使用AddJsonBodyAddBody方法,这两者都会导致序列化,我使用AddParameterwhich 将添加您传入的对象而无需序列化。我创建了一个名为 的方法SerialiseJSON.net用于序列化我们的类。

private object Serialize<T>(T item)
{
    return JsonConvert.SerializeObject(item);
}

This then allows us to use JSON.net's JsonPropertyannotation above your propertys. Here is an example -

这样我们就可以在您的属性上方使用JSON.net'sJsonProperty注释。这是一个例子——

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; }

}

回答by Ryan Kohn

In RestSharp 104.4, the default JsonSerializerdoesn't use the [SerializeAs]attribute, as seen by reviewing the source code.

在 RestSharp 104.4 中,默认情况下JsonSerializer不使用该[SerializeAs]属性,如查看源代码所示

One workaround to this is to create a custom serializer that uses the Json.NET JsonSerializer(a good example is here) and then decorate your properties with the [JsonProperty]attribute, like so:

一种解决方法是创建一个使用 Json.NET 的自定义序列化程序JsonSerializer这里是一个很好的示例),然后使用该[JsonProperty]属性装饰您的属性,如下所示:

<JsonProperty("email")>
Public Property EmailAddress As String

回答by CodeCaster

RestSharp uses SimpleJson. This library doesn't know or respect the [SerializeAs]attribute (which is XML-only anyway), it just outputs the POCO's property name, unless it's compiled with #SIMPLE_JSON_DATACONTRACTdefined, then you can use the [DataContract]attribute to rename properties.

RestSharp 使用SimpleJson。这个库不知道或不尊重[SerializeAs]属性(无论如何都是 XML 的),它只输出 POCO 的属性名称,除非它是用#SIMPLE_JSON_DATACONTRACT定义编译的,然后你可以使用该[DataContract]属性来重命名属性。

So your options seem to be to recompile the SimpleJson library with that define and decorate your properties with the [DataContract(Name="lowercasepropertyname")]attribute, or create a custom serializer that uses a JSON serializer that does respect other attributes as suggested in @Ryan's answer.

因此,您的选择似乎是重新编译 SimpleJson 库,使用该[DataContract(Name="lowercasepropertyname")]属性定义和装饰您的属性,或者创建一个使用 JSON 序列化程序的自定义序列化程序,该序列化程序确实尊重@Ryan的答案中建议的其他属性。

回答by Jigar Patel

You could use following method in the Client side. It is essentially using Newtonsoft deserializer instead of built-in RestSharp deserializer. Newtonsoft deserializer respects DataMember Name property or JsonProperty.

您可以在客户端使用以下方法。它本质上是使用 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));
    }