【问题标题】:JavaScript API - Why is only one JSON key/vaule pair being displayed?JavaScript API - 为什么只显示一个 JSON 键/值对?
【发布时间】:2018-12-11 19:17:08
【问题描述】:

我正在 Github 页面上测试 API。我能够使用 Openweather.org API。完整的 JSON 数据可以在浏览器中查看,但只有一个键/值对“描述”会显示在我的页面上。我尝试将三个 div 标签添加到 HTML,在天气和我要呈现的键之间使用冒号,我尝试只使用一个点。我已经用谷歌搜索了这个问题,但没有找到与我的项目相关的任何内容。

另外,请注意我已经注释掉了两个变量,const tconst 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%);
}

【问题讨论】:

  • 我不清楚您遇到了什么问题。我在您的示例 javascript 中看到有关解析 API 调用结果的错误。你说的是这个问题吗?还是完全不同的东西? SyntaxError: Unexpected token u in JSON at position 0."
  • @RyanWilson 这是我上周解决的错误消息。我在 cmets 中添加了这一点,以提醒自己为什么使用严格模式。目前不应该有任何错误消息。
  • 那有什么问题呢?
  • 我发现了几个问题,我将小提琴更新为这个 (jsfiddle.net/ep84so9m/2),它似乎正在做你想做的事。一个问题是你去哪里获取 temp,temp 是对象 main 的属性,它是数据的属性,而不是天气对象,你正在迭代天气数组,它只包含属性 id、main、description 和 icon 的值.
  • @RyanWilson 你和我同时到达那里。他正在尝试访问天气循环中的所有属性。

标签: javascript json api openweathermap


【解决方案1】:

问题:

正如 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/ 他修改了你的代码,让它看起来像你想要的那样。

希望有帮助!

【讨论】:

  • 很好的解释。经过深思熟虑和解释。 +1
  • @Ryan Gibbs 谢谢,Ryan,这很有帮助!一个快速的问题。为什么你需要使用“数据”作为临时而不是描述?见下文: temp.textContent = ${data.main.temp}...;描述.textContent = ${weather.description}...;似乎它也应该是 data.weather.description 。
  • 因为 'weather' 是 forEach 循环中的局部变量,它等同于 data.weather。你也可以这样做:data.weather.forEach(myVarName=> { console.log(myVarName.main); });
猜你喜欢
  • 2021-06-06
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多