如何使用 Newtonsoft 反序列化复杂的 JSON? (NASA API Neo Feed)
How to deserialize complex JSON with Newtonsoft? (NASA API Neo Feed)
我是论坛新手,遇到了问题。
我正在尝试使用 Newtonsoft 反序列化 NASA API 的 Neo Feed,但出现此错误
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable1[NasaApi.Models.Near_Earth_Objects]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'links', line 1, position 9. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) at NasaApi.Services.NearEarthObjectService.GetAllNeos() in C:\Users\santanitaxx1050\Desktop\NasaApi\NasaApi\Services\NearEarthObjectService.cs:line 18 at lambda_method5(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask
1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
Accept: /
Host: localhost:7008
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Safari/537.36
:method: GET
Accept-Encoding: gzip, deflate, br
Accept-Language: es-ES,es;q=0.9
Cache-Control: no-cache
postman-token: ec30b624-b8b6-770d-57ce-4b6dcda1ffc2
sec-gpc: 1
sec-fetch-site: none
sec-fetch-mode: cors
sec-fetch-dest: empty
我试过了
public async Task<IEnumerable<Near_Earth_Objects>> GetAllNeos()
{
var json = await _httpClient.GetStringAsync($"feed?start_date=2021-11-07&end_date=2021-11-10&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2");
return JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
}
有了这个JSON
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-12&end_date=2021-12-15&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-06&end_date=2021-12-09&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-09&end_date=2021-12-12&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2"
},
"element_count": 76,
"near_earth_objects": {
"2021-12-12": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/2004341?api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2"
},
"id": "2004341",
"neo_reference_id": "2004341",
"name": "4341 Poseidon (1987 KF)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=2004341",
"absolute_magnitude_h": 16.05,
"estimated_diameter": {
"kilometers": {
"estimated_diameter_min": 1.6389095149,
"estimated_diameter_max": 3.6647130844
},
"meters": {
"estimated_diameter_min": 1638.9095149478,
"estimated_diameter_max": 3664.7130843945
},
"miles": {
"estimated_diameter_min": 1.0183708442,
"estimated_diameter_max": 2.277146434
},
"feet": {
"estimated_diameter_min": 5376.9998930214,
"estimated_diameter_max": 12023.337275805
}
},
"is_potentially_hazardous_asteroid": false,
"close_approach_data": [
{
"close_approach_date": "2021-12-12",
"close_approach_date_full": "2021-Dec-12 13:35",
"epoch_date_close_approach": 1639316100000,
"relative_velocity": {
"kilometers_per_second": "17.8282207618",
"kilometers_per_hour": "64181.5947426121",
"miles_per_hour": "39879.9470221525"
},
"miss_distance": {
"astronomical": "0.3316696597",
"lunar": "129.0194976233",
"kilometers": "49617074.634744839",
"miles": "30830620.5431592182"
},
"orbiting_body": "Earth"
}
],
"is_sentry_object": false
},
制作这个模型
public class Near_Earth_Objects
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Nombre { get; set; }
[JsonProperty("estimated_diameter:kilometers:estimated_diameter_min")]
public double DiametroMin { get; set; }
[JsonProperty("estimated_diameter:kilometers:estimated_diameter_max")]
public double DiametroMax { get; set; }
[JsonProperty("close_approach_data:relative_velocity:kilometers_per_hour")]
public double Velocidad { get; set; }
[JsonProperty("close_approach_data: close_approach_date")]
public DateTime Fecha { get; set; }
[JsonProperty("close_approach_date: orbiting_body")]
public string Planeta { get; set; }
}
我的反序列化代码是这样的
public async Task<IEnumerable<Near_Earth_Objects>> GetAllNeos()
{
var json = await _httpClient.GetStringAsync($"feed?start_date=2021-11-07&end_date=2021-11-10&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2");
return JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
}
要查看 JSON 响应,请在 POSTMAN 上尝试此操作:
感谢大家!!
抱歉我的英语不好,我来自西班牙:)
这确实是一个复杂的架构,因此自动生成 DTO 并不容易。因此,您不应该 为属性使用自定义名称。这使得发现问题变得更加困难。
near_earth_objects
部分实际上是一本日常观察的字典。与其创建 near_earth_objects
class,不如使用 Dictionary<string,Observation[]>
.
links
包含指向提要中当前页面、下一页和上一页的链接。这意味着您实际上可以创建一个 class 并在根级别和日常观察中重复使用它
您可以使用 DTO 生成器工具开始,但结果需要修改。工具将无法识别 near_earth_objects
是一个字典,并且很容易最终为每个条目创建新类型。
DTO
使用您的 JSON 示例,我使用 Visual Studio 的 Paste as Json
创建了初始 classes,然后修改它们以使其正常工作。
public class Rootobject
{
public PageLinks links { get; set; }
public int element_count { get; set; }
public Dictionary<string,Observation[]> near_earth_objects { get; set; }
}
public class PageLinks
{
public string? next { get; set; }
public string? prev { get; set; }
public string self { get; set; }
}
Observation
class 使用相同的 PageLinks
class links
属性:
public class Observation
{
public PageLinks links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
其余 classes 不需要修改:
public class Estimated_Diameter
{
public Kilometers kilometers { get; set; }
public Meters meters { get; set; }
public Miles miles { get; set; }
public Feet feet { get; set; }
}
public class Kilometers
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Meters
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Miles
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Feet
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Close_Approach_Data
{
public string close_approach_date { get; set; }
public string close_approach_date_full { get; set; }
public long epoch_date_close_approach { get; set; }
public Relative_Velocity relative_velocity { get; set; }
public Miss_Distance miss_distance { get; set; }
public string orbiting_body { get; set; }
}
public class Relative_Velocity
{
public string kilometers_per_second { get; set; }
public string kilometers_per_hour { get; set; }
public string miles_per_hour { get; set; }
}
public class Miss_Distance
{
public string astronomical { get; set; }
public string lunar { get; set; }
public string kilometers { get; set; }
public string miles { get; set; }
}
测试模型
使用此模型,以下测试通过:
[Fact]
public async Task GetFeed()
{
var client = new HttpClient();
var url = "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-09&end_date=2021-12-12&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2";
var feed = await client.GetFromJsonAsync<Rootobject>(url);
Assert.Equal(76,feed.element_count);
var allObservations = feed.near_earth_objects
.SelectMany(p => p.Value)
.ToList();
Assert.Equal(76,allObservations.Count);
}
错误是因为下面一行:
JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
您收到此错误是因为 API returns 一个 单个对象 但您想将其反序列化为 IEnumerable。
为了解决,将其更改为:
JsonConvert.DeserializeObject<ApiResultDataModel>(json);
和ApiResultDataModel
如下:
public class ApiResultDataModel
{
public Links links { get; set; }
public int element_count { get; set; }
public Dictionary<string, Near_Earth_Objects[]> near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
通过执行此操作,您的数据将成功反序列化:
我希望这个答案对你有帮助。
祝你好运。
我是论坛新手,遇到了问题。
我正在尝试使用 Newtonsoft 反序列化 NASA API 的 Neo Feed,但出现此错误
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable
1[NasaApi.Models.Near_Earth_Objects]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'links', line 1, position 9. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) at NasaApi.Services.NearEarthObjectService.GetAllNeos() in C:\Users\santanitaxx1050\Desktop\NasaApi\NasaApi\Services\NearEarthObjectService.cs:line 18 at lambda_method5(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask
1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)HEADERS
Accept: / Host: localhost:7008 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Safari/537.36 :method: GET Accept-Encoding: gzip, deflate, br Accept-Language: es-ES,es;q=0.9 Cache-Control: no-cache postman-token: ec30b624-b8b6-770d-57ce-4b6dcda1ffc2 sec-gpc: 1 sec-fetch-site: none sec-fetch-mode: cors sec-fetch-dest: empty
我试过了
public async Task<IEnumerable<Near_Earth_Objects>> GetAllNeos()
{
var json = await _httpClient.GetStringAsync($"feed?start_date=2021-11-07&end_date=2021-11-10&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2");
return JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
}
有了这个JSON
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-12&end_date=2021-12-15&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-06&end_date=2021-12-09&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-09&end_date=2021-12-12&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2"
},
"element_count": 76,
"near_earth_objects": {
"2021-12-12": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/2004341?api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2"
},
"id": "2004341",
"neo_reference_id": "2004341",
"name": "4341 Poseidon (1987 KF)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=2004341",
"absolute_magnitude_h": 16.05,
"estimated_diameter": {
"kilometers": {
"estimated_diameter_min": 1.6389095149,
"estimated_diameter_max": 3.6647130844
},
"meters": {
"estimated_diameter_min": 1638.9095149478,
"estimated_diameter_max": 3664.7130843945
},
"miles": {
"estimated_diameter_min": 1.0183708442,
"estimated_diameter_max": 2.277146434
},
"feet": {
"estimated_diameter_min": 5376.9998930214,
"estimated_diameter_max": 12023.337275805
}
},
"is_potentially_hazardous_asteroid": false,
"close_approach_data": [
{
"close_approach_date": "2021-12-12",
"close_approach_date_full": "2021-Dec-12 13:35",
"epoch_date_close_approach": 1639316100000,
"relative_velocity": {
"kilometers_per_second": "17.8282207618",
"kilometers_per_hour": "64181.5947426121",
"miles_per_hour": "39879.9470221525"
},
"miss_distance": {
"astronomical": "0.3316696597",
"lunar": "129.0194976233",
"kilometers": "49617074.634744839",
"miles": "30830620.5431592182"
},
"orbiting_body": "Earth"
}
],
"is_sentry_object": false
},
制作这个模型
public class Near_Earth_Objects
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Nombre { get; set; }
[JsonProperty("estimated_diameter:kilometers:estimated_diameter_min")]
public double DiametroMin { get; set; }
[JsonProperty("estimated_diameter:kilometers:estimated_diameter_max")]
public double DiametroMax { get; set; }
[JsonProperty("close_approach_data:relative_velocity:kilometers_per_hour")]
public double Velocidad { get; set; }
[JsonProperty("close_approach_data: close_approach_date")]
public DateTime Fecha { get; set; }
[JsonProperty("close_approach_date: orbiting_body")]
public string Planeta { get; set; }
}
我的反序列化代码是这样的
public async Task<IEnumerable<Near_Earth_Objects>> GetAllNeos()
{
var json = await _httpClient.GetStringAsync($"feed?start_date=2021-11-07&end_date=2021-11-10&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2");
return JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
}
要查看 JSON 响应,请在 POSTMAN 上尝试此操作:
感谢大家!! 抱歉我的英语不好,我来自西班牙:)
这确实是一个复杂的架构,因此自动生成 DTO 并不容易。因此,您不应该 为属性使用自定义名称。这使得发现问题变得更加困难。
near_earth_objects
部分实际上是一本日常观察的字典。与其创建near_earth_objects
class,不如使用Dictionary<string,Observation[]>
.links
包含指向提要中当前页面、下一页和上一页的链接。这意味着您实际上可以创建一个 class 并在根级别和日常观察中重复使用它
您可以使用 DTO 生成器工具开始,但结果需要修改。工具将无法识别 near_earth_objects
是一个字典,并且很容易最终为每个条目创建新类型。
DTO
使用您的 JSON 示例,我使用 Visual Studio 的 Paste as Json
创建了初始 classes,然后修改它们以使其正常工作。
public class Rootobject
{
public PageLinks links { get; set; }
public int element_count { get; set; }
public Dictionary<string,Observation[]> near_earth_objects { get; set; }
}
public class PageLinks
{
public string? next { get; set; }
public string? prev { get; set; }
public string self { get; set; }
}
Observation
class 使用相同的 PageLinks
class links
属性:
public class Observation
{
public PageLinks links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
其余 classes 不需要修改:
public class Estimated_Diameter
{
public Kilometers kilometers { get; set; }
public Meters meters { get; set; }
public Miles miles { get; set; }
public Feet feet { get; set; }
}
public class Kilometers
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Meters
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Miles
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Feet
{
public float estimated_diameter_min { get; set; }
public float estimated_diameter_max { get; set; }
}
public class Close_Approach_Data
{
public string close_approach_date { get; set; }
public string close_approach_date_full { get; set; }
public long epoch_date_close_approach { get; set; }
public Relative_Velocity relative_velocity { get; set; }
public Miss_Distance miss_distance { get; set; }
public string orbiting_body { get; set; }
}
public class Relative_Velocity
{
public string kilometers_per_second { get; set; }
public string kilometers_per_hour { get; set; }
public string miles_per_hour { get; set; }
}
public class Miss_Distance
{
public string astronomical { get; set; }
public string lunar { get; set; }
public string kilometers { get; set; }
public string miles { get; set; }
}
测试模型
使用此模型,以下测试通过:
[Fact]
public async Task GetFeed()
{
var client = new HttpClient();
var url = "http://www.neowsapp.com/rest/v1/feed?start_date=2021-12-09&end_date=2021-12-12&detailed=false&api_key=Na1sKwJGK1HVeOF4Yx8aLNp4u8ygT5GSSMF26HQ2";
var feed = await client.GetFromJsonAsync<Rootobject>(url);
Assert.Equal(76,feed.element_count);
var allObservations = feed.near_earth_objects
.SelectMany(p => p.Value)
.ToList();
Assert.Equal(76,allObservations.Count);
}
错误是因为下面一行:
JsonConvert.DeserializeObject<IEnumerable<Near_Earth_Objects>>(json);
您收到此错误是因为 API returns 一个 单个对象 但您想将其反序列化为 IEnumerable。
为了解决,将其更改为:
JsonConvert.DeserializeObject<ApiResultDataModel>(json);
和ApiResultDataModel
如下:
public class ApiResultDataModel
{
public Links links { get; set; }
public int element_count { get; set; }
public Dictionary<string, Near_Earth_Objects[]> near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
通过执行此操作,您的数据将成功反序列化: