Api Response в виде списка / выборка всех данных из api response - PullRequest
0 голосов
/ 25 октября 2019

Я новичок в архитектуре .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.

Пожалуйста, помогите ..!

Ответы [ 2 ]

0 голосов
/ 29 октября 2019

Как я могу получить весь ответ, полученный от фактического 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<SearchModel> из фактического ответа, вы не должны использовать var data = k.Value.SelectToken("").Children().First();, который будет извлекать только первый элемент массива docs.

Попытка foreachk.Value.SelectToken("").Children() и возврат List<SearchModel> вместо 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();
    }
0 голосов
/ 26 октября 2019

Ваша модель - это не список, а только один объект, который вы непрерывно перезаписываете в цикле, так что остается только один элемент. Затем вам нужно будет перебирать все документы, а не просто использовать первый (например, k.Value.SelectToken("").Children().First()).

Таким образом, вы сможете решить свою проблему, изменив модель на Список SearchModels и обеспечение итерации по всем документам (это помогает проверять переменные в отладчике, чтобы увидеть, что происходит).

Более простым подходом было бы использование JsonConvert , где выпросто необходимо отразить соответствующую структуру JSON с использованием классов C #, например:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...