附加信息:将值[string]转换为[enum]类型时出错

时间:2016-03-28 13:08:43

标签: c# json enums json.net deserialization

每当我尝试反序列化下面的json字符串时,我都会收到此错误:

错误:

  

其他信息:转换值时出错   " invalid_request_error"输入' ErrorType'。路径'类型',第2行,   第33位。

Json字符串

{
  "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/."
  }
}  

代码

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

枚举

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
}

我想坚持使用Enums而不是字符串 对此有什么好的解决方法?

1 个答案:

答案 0 :(得分:2)

你有几个问题:

  1. 您需要使用StringEnumConverter将枚举序列化为字符串。

  2. 而不是[JsonProperty("enum_name")]您需要使用[EnumMember(Value = "enum_name")]来指定重新映射的枚举名称。您可能还想添加[DataContract]以与数据协定序列化程序完全兼容。

  3. 将JSON字符串解析为JToken后,使用JToken.ToObject()JToken.CreateReader()对其进行反序列化效率会更高。无需序列化为字符串,然后从头开始重新解析。

  4. 因此,您的类型应如下所示:

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

    你的映射器:

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