【问题标题】:Api Response as a List / fetching all the data from api responseApi 响应作为列表/从 api 响应中获取所有数据
【发布时间】:2019-10-25 15:04:21
【问题描述】:

我是 .netcore mvc 架构的新手。我正在尝试使用 api 数据响应,到目前为止我已成功获取数据,但我面临的问题是当 api 响应/结果不止一个时。例如,如果实际的 api 响应如下

  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"title:\"A\""}},
  "response":{"numFound":3,"start":0,"docs":[
      {
        "date":"1970-01-01T00:00:00Z",
        "tstamp":"2019-11-22T12:22:31.698Z",
        "digest":"e23d679991d80d832504e7395d139fe4",
        "contentLength":"25476",
        "boost":0.0,

       "title":["emb- A1]
        "url":"https://www.example.com/a/b/c0/"},
{
        "date":"1970-01-01T00:00:00Z",
        "tstamp":"2019-11-22T12:22:31.698Z",
        "digest":"e23d679991d80d832504e7395d139fe4",
        "contentLength":"25476",
        "boost":0.0,
   "title":["emb - A2]
        "url":"https://www.example.com/a/b/c1/"
},
{
        "date":"1970-01-01T00:00:00Z",
        "tstamp":"2019-11-22T12:22:31.698Z",
        "digest":"e23d679991d80d832504e7395d139fe4",
        "contentLength":"25476",
        "boost":0.0,
   "title":["emb - A3]
        "url":"https://www.example.com/a/b/c2/"
}

我只是得到

{"title":"[\r\n  \"emb- A1","source":"https://www.example.com/a/b/c0/"}

而不是拥有所有的响应数据。

我的代码如下。 型号 SearchModel.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace searchEngineTesting.Models
{
    public class SearchModel
    {
        public string Title;
        public string Source;

    }
}


控制器 EngineController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using searchEngineTesting.Models;

namespace searchEngineTesting.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EngineController : ControllerBase {


        [HttpGet("[action]/{query}")]
        public async Task<IActionResult> Product(string query)
        {
            var model = new SearchModel();
            using (var client = new HttpClient())
            {
                try
                {
                    client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
                    var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
                    response.EnsureSuccessStatusCode();
                    var stringResult = await response.Content.ReadAsStringAsync();
                    var root = (JObject)JsonConvert.DeserializeObject(stringResult);
                    //var details = JsonConvert.DeserializeObject<SearchModel>(stringResult);
                    var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);

                    foreach (var item in items)
                    {
                        if (item.Key == "response")
                        {
                            var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);

                            foreach (var k in key)
                            {
                                if(k.Key == "docs")
                                {
                                    var tests = JsonConvert.DeserializeObject<JArray>(k.Value.ToString());
                                    var data = k.Value.SelectToken("").Children().First();
                                    var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
                                    foreach (var t in test)
                                    {
                                        if (t.Key =="url")
                                        {
                                            model.Source = t.Value.ToString();
                                        }
                                        else if (t.Key == "title")
                                        {
                                            model.Title = t.Value.ToString();                                        }
                                    }
                                }
                            }
                        }
                    }

                    return new JsonResult(model);

                }
                catch (InvalidOperationException httpreq) {
                    return BadRequest("Sorry: There are no results for your query");
                }
            }
        }



    }
}

如何检索从实际 API 获得的全部响应。

请帮忙..!

【问题讨论】:

    标签: list api asp.net-core


    【解决方案1】:

    如何检索从实际 API 获得的全部响应。

    如果您想返回所有实际的 api 响应,那么只需使用以下代码:

    [HttpGet("[action]/{query}")]
    public async Task<IActionResult> Product(string query)
        {
            var model = new SearchModel();
            using (var client = new HttpClient())
            {
                try
                {
                    client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
                    var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
                    response.EnsureSuccessStatusCode();
                    var stringResult = await response.Content.ReadAsStringAsync();
                    var root = (JObject)JsonConvert.DeserializeObject(stringResult);
    
                    return new JsonResult(root);
                }
                catch (InvalidOperationException httpreq)
                {
    
                }
            }
            return Ok()
         }
    

    如果您只想从实际响应中返回List&lt;SearchModel&gt;,则不应使用var data = k.Value.SelectToken("").Children().First();,它只会检索docs 数组的第一个元素。

    尝试 foreach k.Value.SelectToken("").Children() 并返回 List&lt;SearchModel&gt; 而不是 SearchModel,参考

    [HttpGet("[action]/{query}")]
    public async Task<IActionResult> Product(string query)
        {
            //initialize a list SearchModel
            var modelList = new List<SearchModel>();
    
            using (var client = new HttpClient())
            {
                try
                {
                    client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
                    var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
                    response.EnsureSuccessStatusCode();
                    var stringResult = await response.Content.ReadAsStringAsync();
                    var root = (JObject)JsonConvert.DeserializeObject(stringResult);
    
                    var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
    
                    foreach (var item in items)
                    {
                        if (item.Key == "response")
                        {
                            var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
    
                            foreach (var k in key)
                            {
                                if (k.Key == "docs")
                                {
                                    //remove .First()
                                    var arrayData = k.Value.SelectToken("").Children();
                                    foreach(var data in arrayData)
                                    {
                                        var model = new SearchModel();
                                        var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
                                        foreach (var t in test)
                                        {
                                            if (t.Key == "url")
                                            {
                                                model.Source = t.Value.ToString();
                                            }
                                            else if (t.Key == "title")
                                            {
                                                model.Title = t.Value.ToString();
                                            }
                                        }
    
                                        modelList.Add(model);
                                    }
    
                                }
                            }
                        }
                    }
    
                    return new JsonResult(modelList);
    
                }
                catch (InvalidOperationException httpreq)
                {
    
                }
            }
    
            return Ok();
        }
    

    【讨论】:

      【解决方案2】:

      您的模型不是一个列表,而只是一个对象,您将在循环中连续覆盖它,以便只保留一个元素。 然后,您将需要遍历所有文档,而不仅仅是使用第一个(例如 k.Value.SelectToken("").Children().First())。

      因此,您应该能够通过将模型更改为 ListSearchModels 来解决您的问题,并确保遍历所有文档(这有助于在调试器中检查变量以了解发生了什么)。

      更简单的方法是使用JsonConvert,您只需使用 C# 类镜像 JSON 的相关结构,例如:

      public class Document
      {
          public string Title;
          public string Url;
      }
      
      public class Result
      {
          public Response response;
      }
      
      public class Response
      {
          public List<Document> docs;
      }
      

      然后将json简单反序列化为:

      var result = JsonConvert.DeserializeObject<Result>(stringResult);
      

      最后将结果转换为您的SearchModel

      var searchModels = result.response.docs.Select(x => new SearchModel {Source = x.Url, Title = x.Title}).ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-04
        • 1970-01-01
        • 2018-05-31
        • 1970-01-01
        • 2015-02-14
        相关资源
        最近更新 更多