HttpClient 将 JSON 对象解析为列表,而不是 JSON 数组
HttpClient parse JSON object to List, instead of JSON Array
我们的一位客户需要一些数据,这些数据应该从服务提供商处获得。该服务是用 PHP 编写的,比 soap 或 wcf 服务更像一个网络 api,响应格式如下:
{"0":{"Code":"AL","Name":"ALBANIA"},"1":{"Code":"DZ","Name":"ALGERIA"},"2":{"Code":"AD","Name":"ANDORRA"},"3":{"Code":"AO","Name":"ANGOLA"},"4":{"Code":"AI","Name":"ANGUILLA"},"5":{"Code":"AG","Name":"ANTIGUA"},"6":{"Code":"AR","Name":"ARGENTINA"},"7":{"Code":"AM","Name":"ARMENIA"},"8":{"Code":"AW","Name":"ARUBA"},"9":{"Code":"AU","Name":"AUSTRALIA"},"10":{"Code":"AT","Name":"AUSTRIA"},"11":{"Code":"AZ","Name":"AZERBAIJAN"},"12":{"Code":"BS","Name":"BAHAMAS"},"StartTime":"2016-06-13
04:57:15","EndTime":"2016-06-13 04:57:15"}
如您所见,它是一个数组,但采用对象格式,这就是我遇到问题的原因。
我用的是HttpClient,我的模型是这样的:
public class CountryVM
{
public string Code { get; set; }
public string Name { get; set; }
}
我还对其进行了扩展,使其成为以下模型的一部分:
public class CountryResponseVM
{
public List<CountryVM> CountryVMs { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
}
当我运行以下代码时:
using (var client = new HttpClient())
{
var response = client.PostAsync(command, new StringContent(string.Empty)).Result;
if (response.IsSuccessStatusCode)
{
List<CountryVM> readAsAsync = response.Content.ReadAsAsync<List<CountryVM>>().Result;
}
}
无论是 'CountryVM' 还是 'CountryResponseVM' class,它都会抛出以下异常:
An exception of type 'System.Net.Http.UnsupportedMediaTypeException'
occurred in System.Net.Http.Formatting.dll but was not handled in user
code
Additional information: No MediaTypeFormatter is available to read an
object of type 'List`1' from content with media type 'text/html'.
如何重新格式化响应,或者在调用之前将 json 对象解析为数组
ReadAsAsync
方法。
更新
我还有一个模型,在国家下面列出的城市。
城市模型似乎更正确,它有数组而不是对象,并给数组命名,但在所有情况下我仍然有与国家相同的问题。
回复:
{"CityInfo":[{"CityCode":"TIA-","Name":"Albania"},{"CityCode":"TIA-7","Name":"Berat"},{"CityCode":"TIA-3","Name":"Durres"},{"CityCode":"TIA-4","Name":"Korce"},{"CityCode":"TIA-8","Name":"Pogradec"},{"CityCode":"TIA-2","Name":"Sarande"},{"CityCode":"TIA-6","Name":"Shkoder"},{"CityCode":"TIA-1","Name":"Tirana"},{"CityCode":"TIA-5","Name":"Vlore"}],"StartTime":"2016-06-13
06:03:34","EndTime":"2016-06-13 06:03:34"}
型号:
public class CityResponseVM
{
public List<CityVM> CityInfo { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
}
public class CityVM
{
public string CityCode { get; set; }
public string Name { get; set; }
}
并请求:
string command = Otrams.Url+Otrams.GetAction(ServiceAction.CityList) +"&username="+Otrams.Username+"&password="+Otrams.Password+"&gzip=no&country=AL";
using (var client = new HttpClient())
{
var response = client.PostAsync(command, new StringContent(string.Empty)).Result;
if (response.IsSuccessStatusCode)
{
//CityResponseVM readAsAsync = response.Content.ReadAsAsync<CityResponseVM>().Result;
var rawData = response.Content.ReadAsStringAsync().Result;
var myList = JsonConvert.DeserializeObject<IEnumerable<CityVM>>(rawData);
}
}
从 NuGet 中获取 NewtonSoft.JSON 并将其与您的项目一起安装。然后进行以下操作:
用 [Serializable] 或 [DataContract] 属性标记您的 CountryVM class(我总是忘记哪个在哪个位置)
然后,您只需将 Response.Content 转换为 JSON,并将其序列化:
var rawData = Response.Content.ReadAll(); // forgot the proper syntax, just get the content as string
var myList = JsonConvert.DeserializeObject<IEnumerable<CountryVM>>(rawData);
"myList" 现在是一个你想要的可枚举集合。请注意,语法可能是错误的,因为我是在脑海中回复,但该过程是有效的,应该可以解决您的问题。
使用两个对象,一个用于反序列化,一个实际包含结果。
public class MyTempModel
{
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Countries { get; set; }
}
public class MyRealModel : Dictionary<int, CountryVM>
{
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
反序列化:
var myList = JsonConvert.DeserializeObject<MyTempModel>(jsonResult);
var model = new MyRealModel
{
StartTime = myList.StartTime,
EndTime = myList.EndTime
};
foreach (var temp in myList.Countries)
{
// Deserialize the actual ContryVm.
var obj = JsonConvert.DeserializeObject<CountryVM>(temp.Value.ToString());
int key = 0;
int.TryParse(temp.Key, out key);
model.Add(key, obj);
}
这里的关键部分是使用 JsonExtensionData
,如这里所建议的:How to serialize a Dictionary as part of its parent object using Json.Net。它将启用字典格式,具有额外的属性,例如 StartTime
和 EndTime
.
更高级的解决方案是使用 JsonConverter.
查看聊天了解更多信息。
我们的一位客户需要一些数据,这些数据应该从服务提供商处获得。该服务是用 PHP 编写的,比 soap 或 wcf 服务更像一个网络 api,响应格式如下:
{"0":{"Code":"AL","Name":"ALBANIA"},"1":{"Code":"DZ","Name":"ALGERIA"},"2":{"Code":"AD","Name":"ANDORRA"},"3":{"Code":"AO","Name":"ANGOLA"},"4":{"Code":"AI","Name":"ANGUILLA"},"5":{"Code":"AG","Name":"ANTIGUA"},"6":{"Code":"AR","Name":"ARGENTINA"},"7":{"Code":"AM","Name":"ARMENIA"},"8":{"Code":"AW","Name":"ARUBA"},"9":{"Code":"AU","Name":"AUSTRALIA"},"10":{"Code":"AT","Name":"AUSTRIA"},"11":{"Code":"AZ","Name":"AZERBAIJAN"},"12":{"Code":"BS","Name":"BAHAMAS"},"StartTime":"2016-06-13 04:57:15","EndTime":"2016-06-13 04:57:15"}
如您所见,它是一个数组,但采用对象格式,这就是我遇到问题的原因。
我用的是HttpClient,我的模型是这样的:
public class CountryVM
{
public string Code { get; set; }
public string Name { get; set; }
}
我还对其进行了扩展,使其成为以下模型的一部分:
public class CountryResponseVM
{
public List<CountryVM> CountryVMs { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
}
当我运行以下代码时:
using (var client = new HttpClient())
{
var response = client.PostAsync(command, new StringContent(string.Empty)).Result;
if (response.IsSuccessStatusCode)
{
List<CountryVM> readAsAsync = response.Content.ReadAsAsync<List<CountryVM>>().Result;
}
}
无论是 'CountryVM' 还是 'CountryResponseVM' class,它都会抛出以下异常:
An exception of type 'System.Net.Http.UnsupportedMediaTypeException' occurred in System.Net.Http.Formatting.dll but was not handled in user code
Additional information: No MediaTypeFormatter is available to read an object of type 'List`1' from content with media type 'text/html'.
如何重新格式化响应,或者在调用之前将 json 对象解析为数组
ReadAsAsync
方法。
更新
我还有一个模型,在国家下面列出的城市。 城市模型似乎更正确,它有数组而不是对象,并给数组命名,但在所有情况下我仍然有与国家相同的问题。
回复:
{"CityInfo":[{"CityCode":"TIA-","Name":"Albania"},{"CityCode":"TIA-7","Name":"Berat"},{"CityCode":"TIA-3","Name":"Durres"},{"CityCode":"TIA-4","Name":"Korce"},{"CityCode":"TIA-8","Name":"Pogradec"},{"CityCode":"TIA-2","Name":"Sarande"},{"CityCode":"TIA-6","Name":"Shkoder"},{"CityCode":"TIA-1","Name":"Tirana"},{"CityCode":"TIA-5","Name":"Vlore"}],"StartTime":"2016-06-13 06:03:34","EndTime":"2016-06-13 06:03:34"}
型号:
public class CityResponseVM
{
public List<CityVM> CityInfo { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
}
public class CityVM
{
public string CityCode { get; set; }
public string Name { get; set; }
}
并请求:
string command = Otrams.Url+Otrams.GetAction(ServiceAction.CityList) +"&username="+Otrams.Username+"&password="+Otrams.Password+"&gzip=no&country=AL";
using (var client = new HttpClient())
{
var response = client.PostAsync(command, new StringContent(string.Empty)).Result;
if (response.IsSuccessStatusCode)
{
//CityResponseVM readAsAsync = response.Content.ReadAsAsync<CityResponseVM>().Result;
var rawData = response.Content.ReadAsStringAsync().Result;
var myList = JsonConvert.DeserializeObject<IEnumerable<CityVM>>(rawData);
}
}
从 NuGet 中获取 NewtonSoft.JSON 并将其与您的项目一起安装。然后进行以下操作:
用 [Serializable] 或 [DataContract] 属性标记您的 CountryVM class(我总是忘记哪个在哪个位置)
然后,您只需将 Response.Content 转换为 JSON,并将其序列化:
var rawData = Response.Content.ReadAll(); // forgot the proper syntax, just get the content as string
var myList = JsonConvert.DeserializeObject<IEnumerable<CountryVM>>(rawData);
"myList" 现在是一个你想要的可枚举集合。请注意,语法可能是错误的,因为我是在脑海中回复,但该过程是有效的,应该可以解决您的问题。
使用两个对象,一个用于反序列化,一个实际包含结果。
public class MyTempModel
{
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Countries { get; set; }
}
public class MyRealModel : Dictionary<int, CountryVM>
{
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
}
反序列化:
var myList = JsonConvert.DeserializeObject<MyTempModel>(jsonResult);
var model = new MyRealModel
{
StartTime = myList.StartTime,
EndTime = myList.EndTime
};
foreach (var temp in myList.Countries)
{
// Deserialize the actual ContryVm.
var obj = JsonConvert.DeserializeObject<CountryVM>(temp.Value.ToString());
int key = 0;
int.TryParse(temp.Key, out key);
model.Add(key, obj);
}
这里的关键部分是使用 JsonExtensionData
,如这里所建议的:How to serialize a Dictionary as part of its parent object using Json.Net。它将启用字典格式,具有额外的属性,例如 StartTime
和 EndTime
.
更高级的解决方案是使用 JsonConverter.
查看聊天了解更多信息。