json_decode() Not Decoding Valid JSON as Expected

We’re remotely obtaining a list of salon services in the form of JSON. Here is the raw, valid JSON ( the important part to focus on is just the structure e.g. [“Manicure”,[{“id”:1, … }]] )

["Manicure",[{"id":1,"type\_title":"Manicure","option":"Men Manicure","price":20.0,"time":30,"created\_at":"2015-03-13T16:47:30.677Z","updated\_at":"2015-03-13T16:47:30.677Z","category\_id":1},{"id":2,"type\_title":"Manicure","option":"Classic Manicure","price":25.0,"time":45,"created\_at":"2015-03-13T16:47:30.695Z","updated\_at":"2015-03-13T16:47:30.695Z","category\_id":1},{"id":3,"type\_title":"Manicure","option":"Shellac Manicure","price":35.0,"time":45,"created\_at":"2015-03-13T16:47:30.709Z","updated\_at":"2015-03-13T16:47:30.709Z","category\_id":1},{"id":4,"type\_title":"Manicure","option":"Shellac Manicure w/ removal","price":43.0,"time":60,"created\_at":"2015-03-13T16:47:30.719Z","updated\_at":"2015-03-13T16:47:30.719Z","category\_id":1}],"Pedicure",[{"id":5,"type\_title":"Pedicure","option":"Men Pedicure","price":30.0,"time":45,"created\_at":"2015-03-13T16:47:30.729Z","updated\_at":"2015-03-13T16:47:30.729Z","category\_id":2},{"id":6,"type\_title":"Pedicure","option":"Classic Pedicure","price":35.0,"time":45,"created\_at":"2015-03-13T16:47:30.744Z","updated\_at":"2015-03-13T16:47:30.744Z","category\_id":2},{"id":7,"type\_title":"Pedicure","option":"Shellac Pedicure","price":45.0,"time":45,"created\_at":"2015-03-13T16:47:30.754Z","updated\_at":"2015-03-13T16:47:30.754Z","category\_id":2},{"id":8,"type\_title":"Pedicure","option":"Shellac Pedicure w/ removal","price":53.0,"time":60,"created\_at":"2015-03-13T16:47:30.763Z","updated\_at":"2015-03-13T16:47:30.763Z","category\_id":2}],"Mani-Pedi",[{"id":9,"type\_title":"Mani-Pedi","option":"Express Mani-Pedi","price":40.0,"time":60,"created\_at":"2015-03-13T16:47:30.773Z","updated\_at":"2015-03-13T16:47:30.773Z","category\_id":3},{"id":10,"type\_title":"Mani-Pedi","option":"Men Mani-Pedi","price":40.0,"time":60,"created\_at":"2015-03-13T16:47:30.782Z","updated\_at":"2015-03-13T16:47:30.782Z","category\_id":3},{"id":11,"type\_title":"Mani-Pedi","option":"Classic Mani-Pedi","price":50.0,"time":90,"created\_at":"2015-03-13T16:47:30.794Z","updated\_at":"2015-03-13T16:47:30.794Z","category\_id":3},{"id":12,"type\_title":"Mani-Pedi","option":"Shellac Mani-Pedi","price":70.0,"time":90,"created\_at":"2015-03-13T16:47:30.807Z","updated\_at":"2015-03-13T16:47:30.807Z","category\_id":3},{"id":13,"type\_title":"Mani-Pedi","option":"Shellac Mani-Pedi w/ removal","price":78.0,"time":105,"created\_at":"2015-03-13T16:47:30.816Z","updated\_at":"2015-03-13T16:47:30.816Z","category\_id":3},{"id":14,"type\_title":"Mani-Pedi","option":"Shellac Mani \u0026 Classic Pedi","price":60.0,"time":90,"created\_at":"2015-03-13T16:47:30.825Z","updated\_at":"2015-03-13T16:47:30.825Z","category\_id":3},{"id":15,"type\_title":"Mani-Pedi","option":"Shellac Mani \u0026 Classic Pedi w/ removal","price":68.0,"time":100,"created\_at":"2015-03-13T16:47:30.834Z","updated\_at":"2015-03-13T16:47:30.834Z","category\_id":3}]]

We decode the JSON response from the server:

data = json.decode(event.response)

We’d hoped for the categories to act as parents or keys to the nested data for each category e.g. “Manicure” => table: 0x7fe85f4c2fd0 { [1] => { … } } but json_decode() splits the JSON in a way that renders it useless. Console output of what’s returned by json_decode():

table: 0x7fe85f4c2fd0 {   [1] =\> "Manicure"   [2] =\> table: 0x7fe85f4c2fd0 {            [1] =\> table: 0x7fe85f4318d0 {                     [updated\_at] =\> "2015-03-13T16:47:30.677Z"                     [category\_id] =\> 1                     [time] =\> 30                     [price] =\> 20                     [id] =\> 1                     [type\_title] =\> "Manicure"                     [created\_at] =\> "2015-03-13T16:47:30.677Z"                     [option] =\> "Men Manicure"                   }            [2] =\> table: 0x7fe85f4318d0 {                     [updated\_at] =\> "2015-03-13T16:47:30.695Z"                     [category\_id] =\> 1                     [time] =\> 45                     [price] =\> 25                     [id] =\> 2                     [type\_title] =\> "Manicure"                     [created\_at] =\> "2015-03-13T16:47:30.695Z"                     [option] =\> "Classic Manicure"                   } …          }   [3] =\> "Pedicure"   [4] =\> table: 0x7fe85f4c2fd0 {            [1] =\> table: 0x7fe85f4ed9c0 {                     [updated\_at] =\> "2015-03-13T16:47:30.729Z"                     [category\_id] =\> 2                     [time] =\> 45                     [price] =\> 30                     [id] =\> 5                     [type\_title] =\> "Pedicure"                     [created\_at] =\> "2015-03-13T16:47:30.729Z"                     [option] =\> "Men Pedicure"                   }            [2] =\> table: 0x7fe85f4ed9c0 {                     [updated\_at] =\> "2015-03-13T16:47:30.744Z"                     [category\_id] =\> 2                     [time] =\> 45                     [price] =\> 35                     [id] =\> 6                     [type\_title] =\> "Pedicure"                     [created\_at] =\> "2015-03-13T16:47:30.744Z"                     [option] =\> "Classic Pedicure"                   } …          }   [5] =\> "Mani-Pedi"   [6] =\> table: 0x7fe85f4c2fd0 {            [1] =\> table: 0x7fe85f480f50 {                     [updated\_at] =\> "2015-03-13T16:47:30.773Z"                     [category\_id] =\> 3                     [time] =\> 60                     [price] =\> 40                     [id] =\> 9                     [type\_title] =\> "Mani-Pedi"                     [created\_at] =\> "2015-03-13T16:47:30.773Z"                     [option] =\> "Express Mani-Pedi"                   }            [2] =\> table: 0x7fe85f480f50 {                     [updated\_at] =\> "2015-03-13T16:47:30.782Z"                     [category\_id] =\> 3                     [time] =\> 60                     [price] =\> 40                     [id] =\> 10                     [type\_title] =\> "Mani-Pedi"                     [created\_at] =\> "2015-03-13T16:47:30.782Z"                     [option] =\> "Men Mani-Pedi"                   } …          } }

The ‘categories’ do not act as parents to their data. What needs to happen to make the ‘Manicure’, ‘Mani-Pedi’ and ‘Pedicure’ parent/keys to the nested data? 

All your input is greatly appreciated.

I don’t know if it’s just an issue that comes from copy/pasting your JSON into the post, but the JSON isn’t valid because there’s a newline in the last created_at timestamp.

That aside, the JSON is being interpreted correctly. Here’s the gist of what you’re doing:

[   "Manicure",    [       {          "something":1234       }    ],    "Pedicure",    [      {          "something":1234       }    ] ]

… that’s an array with 4 elements, 2 of which are strings and 2 of which are lists. The elements are not related (as you observed)

Here’s what I think you want (key-value pairs):

[{ "Manicure":[ { "something":1234 }] }, { "Pedicure":[{ "something":1234 }] } ]

Thanks _memo,

So should it be expected that json_decode() will interpret:

[   "Manicure",    [       {          "something":1234       }    ],    "Pedicure",    [      {          "something":1234       }    ] ]

As?:

table: 0x7fe85f4c2fd0 {   [1] =\> "Manicure"   [2] =\> {          "something":1234       }   [3] =\> "Pedicure"   [4] =\> {          "something":1234       } }

Yep :slight_smile:

The reasoning is as follows: The JSON contains an array with 4 elements: “Manicure”, a table, “Pedicure”, a table. Json_decode() converts that to a Lua table containing the same 4 elements. Since it’s an array and not key-value pairs, the array elements become the values and the keys are then simply 1, 2, 3, 4. So if you want to use e.g. “Manicure” as a key rather than a value, you need to use the key:value construct of JSON, as in my example above.

That explains it, thanks _memo. 

I don’t know if it’s just an issue that comes from copy/pasting your JSON into the post, but the JSON isn’t valid because there’s a newline in the last created_at timestamp.

That aside, the JSON is being interpreted correctly. Here’s the gist of what you’re doing:

[   "Manicure",    [       {          "something":1234       }    ],    "Pedicure",    [      {          "something":1234       }    ] ]

… that’s an array with 4 elements, 2 of which are strings and 2 of which are lists. The elements are not related (as you observed)

Here’s what I think you want (key-value pairs):

[{ "Manicure":[ { "something":1234 }] }, { "Pedicure":[{ "something":1234 }] } ]

Thanks _memo,

So should it be expected that json_decode() will interpret:

[   "Manicure",    [       {          "something":1234       }    ],    "Pedicure",    [      {          "something":1234       }    ] ]

As?:

table: 0x7fe85f4c2fd0 {   [1] =\> "Manicure"   [2] =\> {          "something":1234       }   [3] =\> "Pedicure"   [4] =\> {          "something":1234       } }

Yep :slight_smile:

The reasoning is as follows: The JSON contains an array with 4 elements: “Manicure”, a table, “Pedicure”, a table. Json_decode() converts that to a Lua table containing the same 4 elements. Since it’s an array and not key-value pairs, the array elements become the values and the keys are then simply 1, 2, 3, 4. So if you want to use e.g. “Manicure” as a key rather than a value, you need to use the key:value construct of JSON, as in my example above.

That explains it, thanks _memo.