javascript - JavaScript API - 为什么只显示一个 JSON 键/值对?
问题描述
我正在 Github 页面上测试 API。我能够使用 Openweather.org API。完整的 JSON 数据可以在浏览器中查看,但只有一个键/值对“描述”会显示在我的页面上。我尝试将三个 div 标签添加到 HTML,在天气和我要呈现的键之间使用冒号,我尝试只使用一个点。我已经用谷歌搜索了这个问题,但没有找到与我的项目相关的任何内容。
另外,请注意我已经注释掉了两个变量const t和const m因为它们会使程序失败。我试图复制const p的格式。任何指导将不胜感激!!
这是 JSON 天气数据:
{
coord: {
lon: -0.13,
lat: 51.51
},
weather: [
{
id: 701,
main: "Mist",
description: "mist",
icon: "50n"
}
],
base: "stations",
main: {
temp: 278.61,
pressure: 1024,
humidity: 81,
temp_min: 276.15,
temp_max: 280.15
},
visibility: 10000,
wind: {
speed: 3.1,
deg: 100
},
clouds: {
all: 20
},
dt: 1544552400,
sys: {
type: 1,
id: 1414,
message: 0.0033,
country: "GB",
sunrise: 1544515001,
sunset: 1544543482
},
id: 2643743,
name: "London",
cod: 200
}
这是我的 JavaScript:
//added strict mode to address following error message, "Uncaught SyntaxError: Unexpected token u in JSON at position 0." 'use strict';
const app = document.getElementById("root");
//add API related image
const weather = document.createElement("img");
weather.src = "weather.jpg";
const container = document.createElement("div");
container.setAttribute("class", "container");
//method to append the logo image and container div to the app root.
app.appendChild(weather);
app.appendChild(container);
// Create a request variable and assign a new XMLHttpRequest object to it.
var request = new XMLHttpRequest();
// Open a new connection, using the GET request on the URL endpoint
request.open("GET", "https://api.openweathermap.org/data/2.5/weather?q=London&APPID=14d276f4fe655e659ec92149c7cebbec", true);
request.onload = function () {
// Begin accessing JSON data here
var data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
data.weather.forEach(weather => {
const card = document.createElement("div");
card.setAttribute("class", "card");
const h1 = document.createElement("h1");
h1.textContent = weather.title;
const p = document.createElement("p");
weather.description = weather.description.substring(0, 300);
p.textContent = `${weather.description}...`;
/*const m = document.createElement("p");
weather.main = weather.main.substring(0, 300);
m.textContent = `${weather.main}...`;
const t = document.createElement("p");
weather.main.temp = weather.main.temp;
t.textContent = `${weather.main.temp}...`; */
// Append the cards to the container element
container.appendChild(card);
// Each card will contain an h1 and a p
card.appendChild(h1);
card.appendChild(p);
});
} else {
const errorMessage = document.createElement("marquee");
errorMessage.textContent = `Hug it, it's not working!`;
app.appendChild(errorMessage);
}
}
// send request
request.send();
这是 HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Testing</title>
<link href="https://fonts.googleapis.com/css?family=Dosis:400,700"
rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body>
<div id="root"></div>
<script src="scripts.js"></script>
</body>
</html>
这是CSS:
* {
box-sizing: border-box
}
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Dosis', sans-serif;
line-height: 1.6;
color: #666;
background: #F6F6F6;
}
#root {
max-width: 1200px;
margin: 0 auto;
}
h1 {
text-align: center;
padding: 1.5rem 2.5rem;
background-image: linear-gradient(120deg, #fbc2eb 0%, #a6c1ee 100%);
margin: 0 0 2rem 0;
font-size: 1.5rem;
color: white;
}
p,t {
padding: 0 2.5rem 2.5rem;
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.card {
margin: 1rem;
background: white;
box-shadow: 2px 4px 25px rgba(0, 0, 0, .1);
border-radius: 12px;
overflow: hidden;
transition: all .2s linear;
}
.card:hover {
box-shadow: 2px 8px 45px rgba(0, 0, 0, .15);
transform: translate3D(0, -2px, 0);
}
@media screen and (min-width: 600px) {
.card {
flex: 1 1 calc(50% - 2rem);
}
}
@media screen and (min-width: 900px) {
.card {
flex: 1 1 calc(33% - 2rem);
}
}
.card:nth-child(2n) h1 {
background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
}
.card:nth-child(4n) h1 {
background-image: linear-gradient(120deg, #ff9a9e 0%, #fecfef 100%);
}
.card:nth-child(5n) h1 {
background-image: linear-gradient(120deg, #ffc3a0 0%, #ffafbd 100%);
}
解决方案
问题:
正如 Ryan Wilson 所讨论的,您看到的问题是您在循环访问天气属性时尝试访问不在 JSON 的天气属性中的参数。为了帮助您理解这一点,请考虑以下 JSON(从您正在使用的 API 截断):
data = {
weather: [
{
id: 721,
main: "Haze",
description: "haze",
icon: "50n"
},
{
id: 300,
main: "Drizzle",
description: "light intensity drizzle",
icon: "09n"
},
{
id: 701,
main: "Mist",
description: "mist",
icon: "50n"
}
],
base: "stations",
main: {
temp: 278.37,
pressure: 1023,
humidity: 87,
temp_min: 276.15,
temp_max: 280.15
}
id: 2643743,
name: "London",
cod: 200
};
此 JSON 对象有多个级别。如果我想访问薄雾天气,我必须使用 data.weather[2].main,它会返回“Mist”。这是因为我从天气数组的第三个项目中获取了属性“main”。
现在,如果我尝试使用 data.weather[2].main.temp 获取“temp”,它不会返回任何内容,因为第三个天气对象下没有“temp”属性。但是,在数据对象根目录的主对象下有一个 temp 属性。要访问它,您需要使用 data.main.temp。
这如何适用于您的代码?
如果您查看您的代码,您可以使用以下命令遍历 data.weather 数组:
data.weather.forEach(weather => {
//...
});
对于该块的每次迭代,变量“天气”将等于 data.weather 数组中的一个对象。因此,如果您要使用:
data.weather.forEach(weather => {
console.log(weather.main);
});
你会得到'Haze',然后是'Drizzle',然后是'Mist'。(基于我上面显示的 JSON)。
我相信你已经想通了,但是你试图通过使用weather.main.temp 来获取温度,这不是一个有效的参数。您将不得不使用 data.main.temp。
我希望这可以为您清除 JSON。
真实答案:
您问题的真正答案“为什么只显示一个键值对?” 其实和我上面说的没有任何关系。如果您在发布问题时查看 API 发送的 JSON,您会看到天气数组中只有一个对象。在撰写本文时,共有三个。您的代码只会创建与天气数组中的项目一样多的卡片。
请务必在此处参考 Ryan Wilson 的 JSFiddle:https ://jsfiddle.net/ep84so9m/2/ 他修改了您的代码以执行您想要的操作。
希望有帮助!