【问题标题】:Searching from JSON从 JSON 中搜索
【发布时间】:2022-10-17 12:51:09
【问题描述】:

我正在尝试为查询开放数据 API 并在表单下方显示搜索结果的数据集构建 AJAX 搜索表单。我想包含一个或多个与我选择的 JSON 数据集中的字段相对应的输入。

提交表单后,我想使用表单数据来查询开放数据 API。我希望允许用户从特定数据集中查找记录子集。

HTML:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" type="text/css" href="style.css" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script type="text/javascript" src="data.js"></script>
  <title></title>
</head>

<body>
  <div class="container">
    <form>
      <input type="text" id="input" placeholder="what you are looking for?">
      <button type="submit">Search</button>
    </form>
  </div>
</body>

</html>

JavaScript:

let x = document.getElementById('input');
let obj;

fetch('https://data.winnipeg.ca/resource/f58p-2ju3.json')
  .then(response => {
    return response.json()
  })
  .then(data => {
    console.log(data)
    obj = JSON.parse(data)
  })

这是我的代码。我希望用户按位置名称搜索,然后整个信息将以表格的形式显示为observationidobservationtimethingidlocationname。仅适用于用户输入的特定locationname

【问题讨论】:

    标签: javascript html css ajax


    【解决方案1】:

    如果您需要在加载的 JSON 数据中进行搜索,则至少需要 3 个方法。

    1. init()此方法首次从 API 加载整个 JSON。
    2. search(inputValue)此方法采用 inputValue 值,以便用于过滤整个 JSON 数据。

      例如,在我的search() 方法中,我使用toLowerCase() 将当前字符串转为小写,并使用indexOf() 字符串方法通过任何给定字符的第一次出现来查找位置名称的记录,所以你可以通过插入特定位置名称的任何字符进行搜索。

      search(inputValue) {
          const results = this.data.filter(x => x.locationname.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
          return this.renderTable(results);
        }
      
      1. renderTable(results)此方法负责渲染从search(inputValue) 方法给出的过滤数据。

      这是一个小演示,您可以在其中看到它的实际效果。

      class SearchJSON {
        data = null;
        constructor() {
          this.init();
        }
        init() {
          fetch('https://data.winnipeg.ca/resource/f58p-2ju3.json')
            .then(response => {
              return response.json();
            })
            .then(data => {
              this.data = data;
            });
        }
        search(inputValue) {
          const results = this.data.filter(x => x.locationname.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
          return this.renderTable(results);
        }
        renderTable(results) {
          let html = "<table><thead><tr><th>Observation Id</th><th>Observation Time</th><th>Thing Id</th><th>Location Name</th></tr></thead></table><table class="result-table"><tbody>";
          let result = null;
          for (let i = 0; i < results.length; i++) {
            result = results[i];
            html += `<tr><td>${result.observationid}</td>
            <td>${result.observationtime}</td>
            <td>${result.thingid}</td>
            <td>${result.locationname}</td>
            <tr>`;
          }
          html += "</tbody></table>";
          return html;
        }
      }
      
      window.onload = () => {
        const form = document.querySelector("form");
        const input = document.getElementById("input");
        const searchJSON = new SearchJSON();
        form.onsubmit = (e) => {
          e.preventDefault();
          const result = searchJSON.search(input.value);
          const formDiv = document.querySelector("form div");
          const div = document.createElement("div");
          div.innerHTML = result;
          if (formDiv !== null) {
            formDiv.parentElement.removeChild(formDiv);
            form.appendChild(div);
          }
          form.appendChild(div);
        };
      };
      .container {
        font-size: 0.8rem;
      }
      
      .container table {
        border-collapse: collapse;
      }
      
      .container table th,
      .container table td {
        border: #ccc solid 1px;
        padding: 0.2rem 0.4rem;
        width: 100px;
      }
      
      .result-table {
        display: inline-block;
        height: 230px;
        overflow: auto;
      }
      <div class="container">
        <form>
          <input type="text" id="input" placeholder="what you are looking for?">
          <button type="submit">Search</button>
        </form>
      </div>

      我不确定端点的功能,但我认为调查https://data.winnipeg.ca/resource/f58p-2ju3.json 端点是否可以接收参数可能会很好,因此您可以使用给定的表单数据将参数发送到端点以返回所需的数据,所以,您可能不需要使用我的示例中的 init() 方法在第一时间加载整个 JSON 数据。

      更新:带有查询字符串参数的端点:

      我找到了一种根据需要使用查询字符串参数的方法。你可以这样使用它:

      `https://data.winnipeg.ca/resource/f58p-2ju3.json?locationname=${inputValue}&$limit=${limit}`
      

      在哪里:

      locationname是要搜索的位置名称。

      $limit是端点使用当前参数检索的最大记录数量。

      此外,您可以使用 async/await 获取请求,如下所示:

      async search(inputValue, limit) {
          const response = await fetch(`https://data.winnipeg.ca/resource/f58p-2ju3.json?locationname=${inputValue}&$limit=${limit}`);
          const results = await response.json();
          return this.renderTable(results);
      }
      

      您可以在这里看到它的实际效果:

      class SearchJSON {
        data = null;
        async search(inputValue, limit) {
          const response = await fetch(`https://data.winnipeg.ca/resource/f58p-2ju3.json?locationname=${inputValue}&$limit=${limit}`);
          const results = await response.json();
          return this.renderTable(results);
        }
        renderTable(results) {
          let html = "<table><thead><tr><th>Observation Id</th><th>Observation Time</th><th>Thing Id</th><th>Location Name</th></tr></thead></table><table class="result-table"><tbody>";
          let result = null;
          for (let i = 0; i < results.length; i++) {
            result = results[i];
            html += `<tr><td>${result.observationid}</td>
            <td>${result.observationtime}</td>
            <td>${result.thingid}</td>
            <td>${result.locationname}</td>
            <tr>`;
          }
          html += "</tbody></table>";
          return html;
        }
      }
      
      window.onload = () => {
        const form = document.querySelector("form");
        const txtLimit = document.getElementById("txtLimit");
        const input = document.getElementById("input");
        const searchJSON = new SearchJSON();
        form.onsubmit = async(e) => {
          e.preventDefault();
          const result = await searchJSON.search(input.value, txtLimit.value);
          const formDiv = document.querySelector("form div");
          const div = document.createElement("div");
          div.innerHTML = result;
          if (formDiv !== null) {
            formDiv.parentElement.removeChild(formDiv);
            form.appendChild(div);
          }
          form.appendChild(div);
        };
      };
      .container {
        font-size: 0.8rem;
      }
      
      .container table {
        border-collapse: collapse;
      }
      
      .container table th,
      .container table td {
        border: #ccc solid 1px;
        padding: 0.2rem 0.4rem;
        width: 100px;
      }
      
      .result-table {
        display: inline-block;
        height: 230px;
        overflow: auto;
      }
      <div class="container">
        <form>
          <input type="number" id="txtLimit" step="10" max="1000" min="0" value="10">
          <input type="text" id="input" placeholder="what you are looking for?">
          <button type="submit">Search</button>
        </form>
      </div>

    【讨论】:

    • 感谢您的回答,但我怎样才能将结果限制为只有 100?我试图使用此代码让 locationname = 'St.詹姆斯·伊斯特”; // 这实际上来自表单输入。 const apiUrl = 'data.winnipeg.ca/resource/f58p-2ju3.json?' + $where=locationname LIKE '%${locationname}%' + '&$limit=100';常量编码URL = encodeURI(apiUrl);
    【解决方案2】:
    1. 将 JSON 分配给变量并使用 $.getJSON

    2. 将以下代码与您的搜索按钮一起使用,

      $("#search").on('keypress keyup 改变输入', function() { var 到达 = $(this).val().toLowerCase();

       $('#matches').text(!arrival.length ? '' : 
      
           dataArr.filter(function(place) {
      
               // look for the entry with a matching `code` value
      
               return (place.title.toLowerCase().indexOf(arrival) !== -1);
      
           }).map(function(place) {
      
               // get titles of matches
      
               return place.title;
      
           }).join('
      ')); // create one text with a line per matched title
      

      });

    【讨论】:

    • 第一次观察?为什么选择 jQuery? OP 在这里没有提到任何与 jQuery 相关的内容。仅为 getJSON() 函数安装它是矫枉过正的。第二个。你在哪里获得 place.title 属性?从提供的 json 文件中,不存在 title 属性
    猜你喜欢
    • 2018-12-27
    • 1970-01-01
    • 2017-08-31
    • 2021-12-23
    • 2021-06-15
    • 2021-02-09
    • 1970-01-01
    • 2018-06-22
    • 2015-03-31
    相关资源
    最近更新 更多