简体   繁体   中英

RestSharp deserialization of Enum Type Property

I have an object

            var testTcc = new TrendingConfigurationConfigDto
            {
                TrendingConfigurationId =1,
                ConfigId = 1,
                DeviceId = 1,
                Selected = true,
                YAxisPosition = YAxisPosition.Left,
                Order = 1,
                Color = "#ffffff",
                Configuration = new BO.Shared.Dtos.List.ConfigurationListDto
                {
                    Id = 1,
                    Name = "configuration",
                    Alias = "configuationAlias",
                    EnableEdit = true,
                    IsBusinessItem = true
                },
                Device = new BO.Shared.Dtos.List.DeviceListDto
                {
                    Id = 1,
                    Name = "Device"
                }
            };

when I serialized it into json as

var jsonTcc = SimpleJson.SerializeObject(testTcc);

it returned string containing json object with YAxisPosition = 1, and when I tried deserializing it using

testTcc = SimpleJson.DeserializeObject<TrendingConfigurationConfigDto>(jsonTcc);

It is giving an exception System.InvalidCastException with message 'Specified cast is not valid'.

I tried changing YAxisPosition value in json string to string "1" or "Left" it was always giving me the same error, until I removed the property YAxisPosition from json string.

I might be missing some thing (an Attribute on enum property or something similar).

Please help me finding a way so that I can Serialize and De-serialize an object which contains Enum type property, using RestSharp.

Note: I tried successful serialization and de-serialization using NewtonSoft. but I do not want a dependency of my Web API Client on NetwonSoft, as I am already using RestSharp.

RestSharp removed JSON.NET support in v103.0 . The default Json Serializer is no longer compatible with Json.NET. You have a couple of options if you want to continue using JSON.NET and maintain backwards compatibility. Beyond that, JSON.NET has more capability and may solve your issues over using the basic .NET serializer which RestSharp now depends on.

Plus you can use the [EnumMember] properties to define custom mappings during deserialization.

Option 1: Implement a custom serializer that uses JSON.NET

To use Json.NET for serialization, copy this code:

/// <summary>
/// Default JSON serializer for request bodies
/// Doesn't currently use the SerializeAs attribute, defers to Newtonsoft's attributes
/// </summary>
public class JsonNetSerializer : ISerializer
{
    private readonly Newtonsoft.Json.JsonSerializer _serializer;

    /// <summary>
    /// Default serializer
    /// </summary>
    public JsonSerializer() {
        ContentType = "application/json";
        _serializer = new Newtonsoft.Json.JsonSerializer {
            MissingMemberHandling = MissingMemberHandling.Ignore,
            NullValueHandling = NullValueHandling.Include,
            DefaultValueHandling = DefaultValueHandling.Include
        };
    }

    /// <summary>
    /// Default serializer with overload for allowing custom Json.NET settings
    /// </summary>
    public JsonSerializer(Newtonsoft.Json.JsonSerializer serializer){
        ContentType = "application/json";
        _serializer = serializer;
    }

    /// <summary>
    /// Serialize the object as JSON
    /// </summary>
    /// <param name="obj">Object to serialize</param>
    /// <returns>JSON as String</returns>
    public string Serialize(object obj) {
        using (var stringWriter = new StringWriter()) {
            using (var jsonTextWriter = new JsonTextWriter(stringWriter)) {
                jsonTextWriter.Formatting = Formatting.Indented;
                jsonTextWriter.QuoteChar = '"';

                _serializer.Serialize(jsonTextWriter, obj);

                var result = stringWriter.ToString();
                return result;
            }
        }
    }

    /// <summary>
    /// Unused for JSON Serialization
    /// </summary>
    public string DateFormat { get; set; }
    /// <summary>
    /// Unused for JSON Serialization
    /// </summary>
    public string RootElement { get; set; }
    /// <summary>
    /// Unused for JSON Serialization
    /// </summary>
    public string Namespace { get; set; }
    /// <summary>
    /// Content type for serialized content
    /// </summary>
    public string ContentType { get; set; }
}

and register it with your client:

var client = new RestClient();
client.JsonSerializer = new JsonNetSerializer();

Option 2: Use a nuget package to use JSON.NET

Instead of doing all of that and having a custom JSON serializer spread throughout your projects is to just use this nuget package: https://www.nuget.org/packages/RestSharp.Newtonsoft.Json . It allows you to use an inherited RestRequest object that defaults to using Newtonsoft.JSON internally like this:

var request = new RestSharp.Newtonsoft.Json.RestRequest(); // Uses JSON.NET

The other option is to set it on every request like this:

var request = new RestRequest();
request.JsonSerializer = new NewtonsoftJsonSerializer();

Disclaimer: I created this project after getting frustrated with having a custom serializer laying around in my projects. I created this to keep things clean and hopefully help others who want backwards compatibility with their RestSharp code that worked prior to v103.

I got it working with the help of PocoJsonSerializerStrategy . RestSharp allows you to specify your own serialization/deserialization strategy, so I created my own strategy that handles enums for me:

public class HandleEnumsJsonSerializerStrategy : PocoJsonSerializerStrategy
{
  public override object DeserializeObject(object value, Type type)
  {
    if (type.IsEnum)
      return Enum.Parse(type, (string)value);
    else
      return base.DeserializeObject(value, type);
  }
}

Now you can pass an object of this class to SimpleJson.DeserializeObject call, like this and your enums are handled elegantly:

SimpleJson.DeserializeObject<JsonObject>(Response.Content, Strategy);

Found solution for this problem:

private IRestClient GetRestClient()
        {
            return new RestClient(url)
                .AddDefaultHeader("Authorization", $"Bearer {token.AccessToken}")
                .AddDefaultHeader("Accept", "*/*")
                .AddDefaultHeader("Accept-Encoding", "gzip, deflate, br")
                .AddDefaultHeader("Connection", "close")
                .UseSystemTextJson(new JsonSerializerOptions
                {
                    Converters = { new JsonStringEnumConverter() }
                });
        }

Ie instructed RestSharp to use System.Text.Json serializer and then instructed the serializer to use JsonStringEnumConverter class to serialize/deserialize enums.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM