0

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

Egor Skriptunoff
  • 906
  • 1
  • 8
  • 23
Xore
  • 11
  • 1
  • 5

4 Answers4

1

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"
  }
}
Piglet
  • 27,501
  • 3
  • 20
  • 43
1

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.

Tom Blodget
  • 20,260
  • 3
  • 39
  • 72
  • This returned me two functions appliable on the request and I used: web.request(URL)() <- I added paranthesis. This gave me the JSON as a String which I could use in serialization afterwards. – Xore Mar 17 '19 at 14:52
0

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

luther
  • 5,195
  • 1
  • 14
  • 24
0

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!

Xore
  • 11
  • 1
  • 5
  • 1
    `()` attempts to invoke a value as a function. (It goes after an expression, of which a variable is a special case.) – Tom Blodget Mar 17 '19 at 02:31
  • This concept isn't really known to me since I mainly code in Java so thanks for clarifying that – Xore Mar 17 '19 at 14:54
  • 1
    Yes, functions are values and when attempting to call a value as a function you can pass whatever list of zero or more parameters you think are appropriate. The result will be a list of zero or more values, _potentially_ a different number for each call. So, you are right; Documentation is very important. – Tom Blodget Mar 17 '19 at 15:02
  • next time you could simply share the error message... error: attempt to index a function value is something different from "I don't know how to work with Lua tables". If you're not sure what type a function returns just print the function call – Piglet Mar 18 '19 at 14:44
  • @Piglet The weird part was it didn't print the function but a table containing two functions. So it showed to me as a table and I thought the request fetched the JSON as a table. There was no error I just couldn't access any values since I didn't know the keys. After I used pairs it printed two function definitions that where I got confused since I expected the JSON entries – Xore Mar 19 '19 at 11:23
  • @Xore print unknown tables `for k,v in pairs(someTable) do print(k,v) end` – Piglet Mar 19 '19 at 12:01