当不存在 属性 时忽略反序列化
Ignore deserialize when no such property exist
我正在使用不在我控制范围内的私人网络服务。
我正在使用登录服务,class 即将反序列化结果
[DataContract]
public class BaseDTO
{
[DataMember]
public string status { get; set; }
[DataMember]
public string msg { get; set; }
[DataMember]
public string code { get; set; }
[DataMember(Name = "data", IsRequired = false)]
public LoginDTO LoginInfo{ get; set; }
}
[DataContract]
public class LoginDTO
{
[DataMember]
public string FirstName{ get; set; }
[DataMember]
public string LastName{ get; set; }
}
这是我尝试过的
public async Task<BaseDTO> InsertString(MyObject insertParameters)
{
try
{
using (var _client = new HttpClient())
{
_client.BaseAddress = new Uri(baseServiceUri);
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent insertHttpcontent = new StringContent(JsonConvert.SerializeObject(insertObject));
var response = await _client.PostAsync(new Uri(baseAccessPoint, UriKind.Relative), insertHttpcontent);
//Throws exception when its invalid
//response.EnsureSuccessStatusCode();
var responseResult = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<BaseDTO>(responseResult, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
Error = JsonDeserializeErrorHandler,
});
}
}
catch (Exception ex)
{
throw;
}
}
如果登录凭据是真实的服务返回 LoginInfo 详细信息,否则它不会提供任何信息,只有状态、消息和代码。
问题是 Json 反序列化器总是尝试反序列化所有内容,即使尝试设置忽略空值也是如此,但似乎不起作用。由于我的服务没有返回 null,它不会提供对象本身。目前我使用 JsonDeserializeErrorHandler 将 errorhandled 属性 设置为 true。
我引用了 this also
Json结果 成功时
{"status":"success","msg":"Welcome!!","code":"","data":{"session_token":"bdadee2cb7597fbb5ceed550ca389440","firsname":"test1","lastname":"test2"}}}}
Json错误时的结果
{"status":"warning","msg":"Incorrect Username or MPIN","code":"","data":[]}
如何更优雅地克服这种情况
#region DeserializeErrorHandling
private void JsonDeserializeErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
{
//var currentError = e.ErrorContext.Error.Message;
e.ErrorContext.Handled = true;
}
#endregion
您的问题是,在一种情况下您得到一个对象 {"session_token":"12", ...}
和一个空数组 []
,在另一种情况下 data
属性。空数组不是 null。这意味着您不能使用相同的类型来反序列化 JSON.
我的建议是对data
属性使用dynamic
然后解析这个值:
[DataContract]
public class BaseDTO
{
// Rest of the properties
[DataMember]
public dynamic data { get; set; }
public LoginDTO LoginInfo
{
get
{
var jObjectData = data as JObject;
if (jObjectData == null)
{
return null;
}
try
{
return jObjectData.ToObject<LoginDTO>();
}
catch
{
return null;
}
}
}
}
您可以在 LoginInfo
属性 中使用更多逻辑。例如你可以根据状态等解析它
注意:您的成功JSON无效,我想这只是一个copy/paste问题。
我正在使用不在我控制范围内的私人网络服务。
我正在使用登录服务,class 即将反序列化结果
[DataContract]
public class BaseDTO
{
[DataMember]
public string status { get; set; }
[DataMember]
public string msg { get; set; }
[DataMember]
public string code { get; set; }
[DataMember(Name = "data", IsRequired = false)]
public LoginDTO LoginInfo{ get; set; }
}
[DataContract]
public class LoginDTO
{
[DataMember]
public string FirstName{ get; set; }
[DataMember]
public string LastName{ get; set; }
}
这是我尝试过的
public async Task<BaseDTO> InsertString(MyObject insertParameters)
{
try
{
using (var _client = new HttpClient())
{
_client.BaseAddress = new Uri(baseServiceUri);
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent insertHttpcontent = new StringContent(JsonConvert.SerializeObject(insertObject));
var response = await _client.PostAsync(new Uri(baseAccessPoint, UriKind.Relative), insertHttpcontent);
//Throws exception when its invalid
//response.EnsureSuccessStatusCode();
var responseResult = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<BaseDTO>(responseResult, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
Error = JsonDeserializeErrorHandler,
});
}
}
catch (Exception ex)
{
throw;
}
}
如果登录凭据是真实的服务返回 LoginInfo 详细信息,否则它不会提供任何信息,只有状态、消息和代码。
问题是 Json 反序列化器总是尝试反序列化所有内容,即使尝试设置忽略空值也是如此,但似乎不起作用。由于我的服务没有返回 null,它不会提供对象本身。目前我使用 JsonDeserializeErrorHandler 将 errorhandled 属性 设置为 true。 我引用了 this also
Json结果 成功时
{"status":"success","msg":"Welcome!!","code":"","data":{"session_token":"bdadee2cb7597fbb5ceed550ca389440","firsname":"test1","lastname":"test2"}}}}
Json错误时的结果
{"status":"warning","msg":"Incorrect Username or MPIN","code":"","data":[]}
如何更优雅地克服这种情况
#region DeserializeErrorHandling
private void JsonDeserializeErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e)
{
//var currentError = e.ErrorContext.Error.Message;
e.ErrorContext.Handled = true;
}
#endregion
您的问题是,在一种情况下您得到一个对象 {"session_token":"12", ...}
和一个空数组 []
,在另一种情况下 data
属性。空数组不是 null。这意味着您不能使用相同的类型来反序列化 JSON.
我的建议是对data
属性使用dynamic
然后解析这个值:
[DataContract]
public class BaseDTO
{
// Rest of the properties
[DataMember]
public dynamic data { get; set; }
public LoginDTO LoginInfo
{
get
{
var jObjectData = data as JObject;
if (jObjectData == null)
{
return null;
}
try
{
return jObjectData.ToObject<LoginDTO>();
}
catch
{
return null;
}
}
}
}
您可以在 LoginInfo
属性 中使用更多逻辑。例如你可以根据状态等解析它
注意:您的成功JSON无效,我想这只是一个copy/paste问题。