Search code examples
c++jsonqtxmlhttprequestqml

How to properly set an API call in QML using XMLHttpRequest


I am building a small weather API as exercise to use QML and properly operate an API call using OpenWeather and you can see there a typical API response.

The problem I am having is that I can't get the API call to work. After setting a minimal example with some cities that you can see below, right next to the city it should appear the symbol of the weather, but it does not happen. The list of the icon can be found here. Source code of the MVE can be found here for completeness.

The error from the compiler: qrc:/main.qml:282: SyntaxError: JSON.parse: Parse error

This is what is happening

current

This is what is expected

expected

Typical API JSON response can be found both here and below:

{
  "coord": {
    "lon": -122.08,
    "lat": 37.39
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 282.55,
    "feels_like": 281.86,
    "temp_min": 280.37,
    "temp_max": 284.26,
    "pressure": 1023,
    "humidity": 100
  },
  "visibility": 16093,
  "wind": {
    "speed": 1.5,
    "deg": 350
  },
  "clouds": {
    "all": 1
  },
  "dt": 1560350645,
  "sys": {
    "type": 1,
    "id": 5122,
    "message": 0.0139,
    "country": "US",
    "sunrise": 1560343627,
    "sunset": 1560396563
  },
  "timezone": -25200,
  "id": 420006353,
  "name": "Mountain View",
  "cod": 200
} 

Below a snippet of code related to the API call:

main.qml

// Create the API getcondition to get JSON data of weather
function getCondition(location, index) {
    var res
    var url = "api.openweathermap.org/data/2.5/weather?id={city id}&appid={your api key}"
    var doc = new XMLHttpRequest()
    // parse JSON data and put code result into codeList
    doc.onreadystatechange = function() {
        if(doc.readyState === XMLHttpRequest.DONE) {
            res = doc.responseText
            // parse data
            var obj = JSON.parse(res)  // <-- Error Here
            if(typeof(obj) == 'object') {
                if(obj.hasOwnProperty('query')) {
                    var ch = onj.query.results.channel
                    var item = ch.item
                    codeList[index] = item.condition["code"]
                }
            }
        }
    }
    doc.open('GET', url, true)
    doc.send()
}

In order to solve this problem I consulted several sources, first of all : official documentation and the related function. I believe it is correctly set, but I added the reference for completeness. Also I came across this one which explained how to simply apply XMLHttpRequest. Also I dug more into the problem to find a solution and also consulted this one which also explained how to apply the JSON parsing function. But still something is not correct.

Thanks for pointing in the right direction for solving this problem.


Solution

  • Below the answer to my question. I was not reading properly the JSON file and after console logging the problem the solution is below. code was correct from beginning, only the response needed to be reviewed properly and in great detail being the JSON response a bit confusing:

    function getCondition() {
        var request = new XMLHttpRequest()
        request.open('GET', 'http://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=key', true);
        request.onreadystatechange = function() {
            if (request.readyState === XMLHttpRequest.DONE) {
                if (request.status && request.status === 200) {
                    console.log("response", request.responseText)
                    var result = JSON.parse(request.responseText)
                } else {
                    console.log("HTTP:", request.status, request.statusText)
                }
            }
        }
        request.send()
    }
    

    Hope that helps!