Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Additional information: Error converting value [string] to type [enum]

I am receiving this error whenever I try to deserialize the json string below:

Error:

Additional information: Error converting value "invalid_request_error" to type 'ErrorType'. Path 'type', line 2, position 33.

Json string

{
  "error": {
    "type": "invalid_request_error",
    "message": "Invalid request (check that your POST content type is application/x-www-form-urlencoded). If you have any questions, we can help at https://support.stripe.com/."
  }
}  

Code

private void btnDeserialize_Click(object sender, EventArgs e)
{
    var r = Components.JsonMapper.MapFromJson<Components.DTO.Error>(txtToDeserialize.Text, "error");
    txtDeserialized.Text = JsonConvert.SerializeObject(r);
}  

JsonMapper

public static class JsonMapper
{
    public static T MapFromJson<T>(string json, string parentToken = null)
    {
        var jsonToParse = string.IsNullOrEmpty(parentToken) ? json : JObject.Parse(json).SelectToken(parentToken).ToString();

        return JsonConvert.DeserializeObject<T>(jsonToParse);
    }
}  

Enum

public enum ErrorCode
{
    Default,

    [JsonProperty("invalid_number")]
    InvalidNumber,

    [JsonProperty("invalid_expiry_month")]
    InvalidExpiryMonth,

    [JsonProperty("invalid_expiry_year")]
    InvalidExpiryYear,

    [JsonProperty("invalid_cvc")]
    InvalidCvc,

    [JsonProperty("incorrect_number")]
    IncorrectNumber,

    [JsonProperty("expired_card")]
    ExpiredCard,

    [JsonProperty("incorrect_cvc")]
    IncorrectCvc,

    [JsonProperty("incorrect_zip")]
    IncorrectZip,

    [JsonProperty("card_declined")]
    CardDeclined,

    [JsonProperty("missing")]
    Missing,

    [JsonProperty("processing_error")]
    ProcessingError
}

public enum ErrorType
{
    Default,

    [JsonProperty("api_connection_error")]
    ApiConnectionError,

    [JsonProperty("api_error")]
    ApiError,

    [JsonProperty("authentication_error")]
    AuthenticationError,

    [JsonProperty("card_error")]
    CardError,

    [JsonProperty("invalid_request_error")]
    InvalidRequestError,

    [JsonProperty("rate_limit_error")]
    RateLimitError
}

I want to stick on using Enums rather than string.
What could be the good workaround for this?

like image 352
fiberOptics Avatar asked Oct 18 '22 12:10

fiberOptics


1 Answers

You have a few issues:

  1. You need to use StringEnumConverter to serialize enums as strings.

  2. Rather than [JsonProperty("enum_name")] you need to use [EnumMember(Value = "enum_name")] to specify a remapped enum name. You might also want to add [DataContract] for full compatibility with the data contract serializer.

  3. Once you have parsed your JSON string into a JToken, it will be more efficient to deserialize it using JToken.ToObject() or JToken.CreateReader(). No need to serialize to a string then re-parse from scratch.

Thus your types should look like:

[DataContract]
public enum ErrorCode
{
    Default,

    [EnumMember(Value = "invalid_number")]
    InvalidNumber,

    [EnumMember(Value = "invalid_expiry_month")]
    InvalidExpiryMonth,

    [JsonProperty("invalid_expiry_year")]
    InvalidExpiryYear,

    [EnumMember(Value = "invalid_cvc")]
    InvalidCvc,

    [EnumMember(Value = "incorrect_number")]
    IncorrectNumber,

    [EnumMember(Value = "expired_card")]
    ExpiredCard,

    [EnumMember(Value = "incorrect_cvc")]
    IncorrectCvc,

    [EnumMember(Value = "incorrect_zip")]
    IncorrectZip,

    [EnumMember(Value = "card_declined")]
    CardDeclined,

    [EnumMember(Value = "missing")]
    Missing,

    [EnumMember(Value = "processing_error")]
    ProcessingError
}

public class Error
{
    public ErrorType type { get; set; }
    public string message { get; set; }
}

[DataContract]
public enum ErrorType
{
    Default,

    [EnumMember(Value = "api_connection_error")]
    ApiConnectionError,

    [EnumMember(Value = "api_error")]
    ApiError,

    [EnumMember(Value = "authentication_error")]
    AuthenticationError,

    [EnumMember(Value = "card_error")]
    CardError,

    [EnumMember(Value = "invalid_request_error")]
    InvalidRequestError,

    [EnumMember(Value = "rate_limit_error")]
    RateLimitError
}

And your mapper:

public static class JsonMapper
{
    private static JsonReader CreateReader(string json, string parentToken)
    {
        if (string.IsNullOrEmpty(parentToken))
            return new JsonTextReader(new StringReader(json));
        else
        {
            var token = JToken.Parse(json).SelectToken(parentToken);
            return token == null ? null : token.CreateReader();
        }
    }

    public static T MapFromJson<T>(string json, string parentToken = null)
    {
        var settings = new JsonSerializerSettings { Converters = new [] { new StringEnumConverter() } };
        using (var reader = CreateReader(json, parentToken))
        {
            if (reader == null)
                return default(T);
            return JsonSerializer.CreateDefault(settings).Deserialize<T>(reader);
        }
    }
}
like image 194
dbc Avatar answered Oct 21 '22 09:10

dbc