提问人:Adão Gama 提问时间:6/3/2021 最后编辑:Mr. PolywhirlAdão Gama 更新时间:6/3/2021 访问量:170
如何使用JSON数据并忽略重复值?
How to consume JSON data and ignore repeated values?
问:
我正在使用 Google Books API 来显示简单图书搜索的结果。但是,在执行搜索时,某些项目会重复返回。参见:图书搜索
为了获取此数据并以 HTML 格式显示,我正在这样做:
var result = document.getElementById("result");
var cover, title, author, book_id;
function handleResponse(response) {
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
// Create elements
figure = document.createElement("figure");
aEmp = document.createElement("a");
aId = document.createElement("a");
img = document.createElement("img");
figcap = document.createElement("figcaption");
// Get data from JSON
try {
cover = item.volumeInfo.imageLinks.thumbnail;
title = item.volumeInfo.title;
author = item.volumeInfo.authors;
book_id = item.id;
} catch (error) {
continue;
} finally {
// Set value to elements e send to HTML
result.appendChild(figure);
aEmp.appendChild(img);
aId.innerHTML = "ADICIONAR";
aId.href = `/add/${book_id}`;
aId.classList.add("dropdown");
figure.appendChild(aId);
figure.appendChild(aEmp);
img.src = cover;
figcap.innerHTML += `${title}<br>${author}`;
figure.appendChild(figcap);
}
}
}
document.querySelector("form").addEventListener("submit", function (e) {
result.innerHTML = "";
search = document.getElementById("search").value;
var script = document.createElement("script");
script.src = `https://www.googleapis.com/books/v1/volumes?q=${search}&callback=handleResponse`;
document.body.appendChild(script);
e.preventDefault();
});
这是我上传的图片上使用的 JSON 示例:
https://www.googleapis.com/books/v1/volumes?q=$harry+potter&callback=handleResponse
答:
1赞
Alex Weinstein
6/3/2021
#1
看起来 Google 响应数组中的每个项目都包含一个唯一的 ID。在回调函数中,遍历返回结果的数组;记住已经在字典/哈希表中看到的 ID。如果之前看到的 ID 再次显示,只需跳过该记录即可。
评论
0赞
Adão Gama
6/3/2021
好主意!我会尝试这样做。
1赞
jateen
6/3/2021
#2
浏览了您在最后提供的 JSON 数据,但我没有发现 API 响应有任何重复。无法弄清楚重复在数据中的确切位置。
评论
0赞
Adão Gama
6/3/2021
是的,我也意识到了这一点。我不知道为什么会这样。
0赞
Prabhat Mishra
6/3/2021
嗨,@jateen,欢迎来到SO!考虑为此类讨论添加注释。
1赞
Mr. Polywhirl
6/3/2021
#3
我在你们的 API 搜索中没有看到任何重复的值。
但是,我确实用 promise 替换了脚本插入回调 hack。这应该会更好。fetch
const results = document.querySelector('.results');
const googleBooksApi = 'https://www.googleapis.com/books/v1';
const formatList = (items) => {
switch (items.length) {
case 0: return '';
case 1: return items[0];
case 2: return items.join(' and ');
default: return `${items.slice(0, -1).join(', ')} and ${[...items].pop()}`;
}
};
// Convenience promise
const fetchBooks = (path) =>
fetch(`${googleBooksApi}/${path}`)
.then(response => response.json());
const queryBooksVolumes = (term) =>
fetchBooks(`volumes?q=${term.replace(' ', '+')}`);
const addBook = (book) => {
// Create elements
const figure = document.createElement('figure');
const aEmp = document.createElement('a');
const aId = document.createElement('a');
const img = document.createElement('img');
const figcap = document.createElement('figcaption');
const figcapTitle = document.createElement('div');
const figcapAuthors = document.createElement('div');
// Destructure data fields from book object (JSON)
const {
id: bookId,
volumeInfo: {
title,
authors,
publishedDate,
imageLinks: { thumbnail }
}
} = book;
const year = new Date(publishedDate).getFullYear();
figure.classList.add('figure');
aEmp.appendChild(img);
aId.innerHTML = 'ADICIONAR';
aId.href = `/add/${bookId}`;
aId.classList.add('dropdown');
figure.appendChild(aId);
figure.appendChild(aEmp);
img.src = thumbnail;
figcapTitle.classList.add('figcap-title');
figcapTitle.textContent = `${title} (${year})`;
figcapAuthors.classList.add('figcap-authors');
figcapAuthors.textContent = formatList(authors);
figcap.append(figcapTitle);
figcap.append(figcapAuthors);
figure.appendChild(figcap);
results.appendChild(figure);
};
const populateResults = ({ items }) => items
.sort((
{ volumeInfo: { title: a } },
{ volumeInfo: { title: b } }
) =>
a.localeCompare(b))
.forEach(addBook);
const handleSearch = (e) => {
e.preventDefault();
const query = e.target.elements.search.value.trim();
results.innerHTML = '';
if (query.length > 0) {
queryBooksVolumes(query).then(populateResults);
}
};
document.forms['book-search'].addEventListener('submit', handleSearch);
html, body { width 100%; height: 100%; margin: 0; padding: 0; }
form { padding: 0.5em; }
.results {
display: flex;
flex-direction: row;
/*flex-wrap: wrap;*/
align-items: top;
}
form label { font-weight: bold; }
form label::after { content: ':'; }
.figure {
display: flex;
flex-direction: column;
justify-content: center;
border: thin solid grey;
align-items: center;
padding: 0.5em;
}
.figcap-title { font-weight: bold; }
.figcap-authors { font-style: italic; }
.figure img {
margin: 0.5em 0;
}
<form name="book-search">
<label>Book Title</label>
<input type="text" name="search" value="Harry Potter" placeholder="Enter a book title..."/>
<button>Search</button>
</form>
<div class="results"></div>
评论
0赞
Adão Gama
6/3/2021
非常感谢,看起来它真的会好多了。我会申请。
评论