Lua access indeces from table generated from JSON

2k Views Asked by At

So, I am bound to use Lua for getting weather data from the Openweathermap API. I managed to send a http request to return and store all data but now I am stuck with a Lua table I don't know how work with. I am very new to Lua and I didn't find any guide or similar regarding such a deep nested table in Lua.

In particular I am just interested in the field called temp in main. Here is a sample response from the API: Sample request response

The dependencies are Lua's socket.http and this json to Lua table formatter. Here is my basic code structure

json = require ("json")
web = require ("socket.http")

local get = json.decode(web.request(<API Link>))

"get" now stores a table I don't know how to work with

4

There are 4 best solutions below

6
On BEST ANSWER

After 2 days I finally found the error. I was working in a Minecraft Mod called OpenComputers which utilizes Lua. It seems like the mod uses a own version of socket.http and every time I wanted to print the response it returned two functions to use with request. I found out that if I put a "()" after the variable it returned the Response as a String and with the JSON library I could decode it into a workable table.

Side note: I could access the weather like this: json_table["weather"]["temp"]

The mod is pretty poorly documented on the http requests so I had to figure this out by myslef. Thanks for your responses, in the end the error was as always very unexpected!

0
On

That sample response appears to have many subtables that have a main in them. Try this: get.list[1].main.temp.

0
On

If you don't know how to work with Lua tables you probably should learn the very basics of Lua. Refer to https://www.lua.org/start.html

The json string encodes a Lua table with all it's keys and values.

You can either read how the encoder encodes a table or you simply encode your own table and analyze the resulting json string.

print(json.encode({1,2,3}))

[1,2,3]

print(json.encode({a=1, b={1,2}, [3]="test"}))

{"3":"test","b":[1,2],"a":1}

and so on...

There's always table keys and values, separated by a colon. Values can be numbers, strings, tables... If the table only has numeric keys starting from one the value is a list of those values in brackets. If you have different keys in a table its encapsulated in curly brackets...

So let's have a look at your results. I'll remove 39 of the 40 entries to shorten it. I'll also indent to make the structure a bit more readable.

{
  "cod":"200",
  "message":0.0036,
  "cnt":40,
  "list":[{
          "dt":1485799200,
          "main":{
                 "temp":261.45,
                 "temp_min":259.086,
                 "temp_max":261.45,
                 "pressure":1023.48,
                 "sea_level":1045.39,
                 "grnd_level":1023.48,
                 "humidity":79,
                 "temp_kf":2.37},
                 "weather":[
                          {
                           "id":800,
                           "main":"Clear",
                           "description":"clear sky",
                           "icon":"02n"
                           }],
                 "clouds":{"all":8},
                 "wind":{"speed":4.77,"deg":232.505},
                 "snow":{},
                 "sys":{"pod":"n"},
                 "dt_txt":"2017-01-30 18:00:00"}
       ],
  "city":{
        "id":524901,
        "name":"Moscow",
        "coord":{
               "lat":55.7522,
               "lon":37.6156
         },

        "country":"none"
  }
}
1
On

With the help of https://www.json2yaml.com/, the structure is:

cod: '200'
message: 0.0036
cnt: 40
list:
- dt: 1485799200
  main:
    temp: 261.45
    temp_min: 259.086
    temp_max: 261.45
    pressure: 1023.48
    sea_level: 1045.39
    grnd_level: 1023.48
    humidity: 79
    temp_kf: 2.37
  weather:
  - id: 800
    main: Clear
    description: clear sky
    icon: 02n
  clouds:
    all: 8
  wind:
    speed: 4.77
    deg: 232.505
  snow: {}
  sys:
    pod: n
  dt_txt: '2017-01-30 18:00:00'
…
- dt: 1486220400
…
city:
  id: 524901
  name: Moscow
  coord:
    lat: 55.7522
    lon: 37.6156
  country: none

So,

for index, entry in ipairs(get.list) do
    print(index, entry.dt, entry.main.temp)
end

ipairs iterates over the positive integer keys in the table, up to but not including the first integer without a value. It seems that's the way the JSON library represent a JSON array.