每当我试图反序列化下面的json字符串时,我都会收到这个错误:
错误:
附加信息:转换值时出错"invalid_request_error"以键入"ErrorType"。路径"type",第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
}
我想坚持使用枚举而不是字符串
解决这个问题的好办法是什么?
您有几个问题:
-
您需要使用
StringEnumConverter
将枚举序列化为字符串。 -
您需要使用
[EnumMember(Value = "enum_name")]
而不是[JsonProperty("enum_name")]
来指定重新映射的枚举名称。为了与数据协定序列化程序完全兼容,您可能还希望添加[DataContract]
。 -
一旦您将JSON字符串解析为
JToken
,使用JToken.ToObject()
或JToken.CreateReader()
对其进行反序列化将更加高效。无需序列化为字符串,然后从头开始重新解析。
因此,你的类型应该看起来像:
[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);
}
}
}