How to Efficiently Map Nested JSON to Custom Lua Data Structures in a REST API Client?

68 Views Asked by At

I'm working on a REST API client in Lua that consumes data from a third-party service. The service returns deeply nested JSON objects, and I need to map these to more simplified Lua tables for easier manipulation and data analysis. I've explored using libraries like cjson for basic deserialization, but I'm struggling with mapping the nested JSON to my custom data structures efficiently.

Here's a simplified example of the JSON object returned by the API:

{
  "data": {
    "id": 1,
    "attributes": {
      "name": "John",
      "details": {
        "age": 30,
        "address": {
          "street": "123 Main St",
          "city": "Anytown"
        }
      }
    }
  }
}

And here's what I would like to map this to in Lua:

Person = {
  id = 1,
  name = "John",
  age = 30,
  street_address = "123 Main St",
  city = "Anytown"
}

Is there a best practice for this type of mapping? Are there any Lua libraries that can assist with this, or should I be writing custom mapping functions? I'm concerned about both code maintainability and performance.

Thank you in advance for any insights or recommendations!

1

There are 1 best solutions below

0
ESkri On BEST ANSWER

The "traversing JSON" functionality is useful here.

local json = require"json"
local s = [[
{
   "data": {
      "id": 1,
      "attributes": {
         "name": "John",
         "details": {
            "age": 30,
            "address": {
               "street": "123 Main St",
               "city": "Anytown"
            }
         }
      }
   }
}
]]
local Person = {}

json.traverse(s,
   function (path, json_type, value, pos, pos_last)
      local path_str = table.concat(path, "/")
      print("DEBUG:", path_str, json_type, value, pos, pos_last)
      if json_type == "number" or json_type == "string" then
         Person[path[#path]] = value
      end
   end
)

print"RESULT"
for k,v in pairs(Person) do
   print(k, v)
end

Output:

DEBUG:                                          object  nil          1    nil
DEBUG:  data                                    object  nil          14   nil
DEBUG:  data/id                                 number  1            28   28
DEBUG:  data/attributes                         object  nil          51   nil
DEBUG:  data/attributes/name                    string  John         70   75
DEBUG:  data/attributes/details                 object  nil          98   nil
DEBUG:  data/attributes/details/age             number  30           119  120
DEBUG:  data/attributes/details/address         object  nil          146  nil
DEBUG:  data/attributes/details/address/street  string  123 Main St  173  185
DEBUG:  data/attributes/details/address/city    string  Anytown      211  219
RESULT
name    John
street  123 Main St
city    Anytown
age     30
id      1

The library is here