[Question]
  [
## Description
Given an object (json), write code to extract all the keys from it. This is a question that I really wanted to ask everybody for a long time ago but I did not have time to write it up. It can be helpful in some cases in your daily work.
## Rule:
* You can use any parse function to get the JSON object, it does not cost you any bytes
* Since a JSON object is a data structure that is not available in some languages, you can use any kind of data that has a similar structure in your favorite language.
* To be clear, the input to your function should be a JSON object if it can.
* The object can have nested keys.
* The object can contain arrays and if it contains an array you will use the index of each element as a key.
* Output can be a list with any format but it is preferred to be line by line.
* The output keys can be arranged in **any order**, it does not matter.
* Shortest bytes for each language will be win.
* You can use any delimiter between each child key and its parent. Here I use `.` (please see the sample output for more detail).
* The key can be a special character. For example:
The input I got from @tsh
```
{"":{"":4,".":5},".":2,"..":3}
```
But this is a special case and it is not required to handle it. You are better to avoid it.
## Example
Given an object:
```
A = {
"name" : {
  "first": "jane",
  "last": "doe"
},
"lang" : ["html", "css"]
}
```
Then the output should be:
```
"name"
"name.first"
"name.last"
"lang"
"lang.0"
"lang.1"
```
The index key (`0` and `1`) are a little tricky here, so for some languages like Javascript, it can be `[0]` and `[1]` instead.
So the example below is also correct:
```
"name"
"name.first"
"name.last"
"lang"
"lang[0]"
"lang[1]"
```
## A Sample test case:
### Input:
```
{
    "quiz": {
        "sport": {
            "q1": {
                "question": "Which one is a correct team name in the NBA?",
                "options": [
                    "New York Bulls",
                    "Los Angeles Kings",
                    "Golden State Warriors",
                    "Houston Rockets"
                ],
                "answer": "Houston Rockets"
            }
        },
        "maths": {
            "q1": {
                "question": "5 + 7 = ?",
                "options": [
                    "10",
                    "11",
                    "12",
                    "13"
                ],
                "answer": "12"
            },
            "q2": {
                "question": "12 - 8 = ?",
                "options": [
                    "1",
                    "2",
                    "3",
                    "4"
                ],
                "answer": "4"
            }
        }
    }
}
```
### Output:
```
[
  "quiz",
  "quiz.sport",
  "quiz.sport.q1",
  "quiz.sport.q1.question",
  "quiz.sport.q1.options",
  "quiz.sport.q1.options.0",
  "quiz.sport.q1.options.1",
  "quiz.sport.q1.options.2",
  "quiz.sport.q1.options.3",
  "quiz.sport.q1.answer",
  "quiz.maths",
  "quiz.maths.q1",
  "quiz.maths.q1.question",
  "quiz.maths.q1.options",
  "quiz.maths.q1.options.0",
  "quiz.maths.q1.options.1",
  "quiz.maths.q1.options.2",
  "quiz.maths.q1.options.3",
  "quiz.maths.q1.answer",
  "quiz.maths.q2",
  "quiz.maths.q2.question",
  "quiz.maths.q2.options",
  "quiz.maths.q2.options.0",
  "quiz.maths.q2.options.1",
  "quiz.maths.q2.options.2",
  "quiz.maths.q2.options.3",
  "quiz.maths.q2.answer"
]
```
This is my solution using [jq](https://stedolan.github.io/jq/download/):
```
jq -r '[paths|map(.|tostring)|join(".")]'
```
Full code:
```
jq -r '[paths|map(.|tostring)|join(".")]' file.json
```
The content of `file.json` is an object from input
  
[Answer]
# [JavaScript (V8)](https://v8.dev/), 72 bytes
An edited version to support literal `false`, `true` and `null` values.
```
f=(o,s)=>!o|[o]==o||Object.keys(o).map(k=>f(o[k],k=s?s+[,k]:k,print(k)))
```
[Try it online!](https://tio.run/##nZJBT9wwEIXv@RVTnxIREFlARSsFBBcqgajUHhCKcjDBu@t14kk9XhB089u3sUNBy@JW7CWOv3nzMvOUOX/gVBnZ2t2H49VqkseYUpKffMFlgWWe43L5/W4uKrunxBPFmOw1vI1VfjKJsVBlqnI6pZ0iVeVYpa2R2sYqSZLVJP4dATC9qGsGY3Bn6sCE1yQc8S8eWbPwxJ0eaN544BxcizRk2RjYnGvB0gHWfGD3KFhPOt9Ycz11jQWb2aZmKbCKiJVRl0TDaEkUDYP14l8L@cz@fsQTatHYNTQIsw32YiDIStRujJuZrGaAWoAkqNCYPjGwgjfglgGp4fr87PRl@DUXbJ0H9SbFRtELrsUj3KJRcN5nSB9YeNUVEpzpqagFwaXU06DwAut7oeGn5VbADTdGGgyKvy3IooYfWClh2Yam/GAfrulRGJfJP5q711v3ZsEabme0Xf5HsANfIYftIs72QwFkWbAyClYOPptU77UeT/ougdH/E8hGsAvH20cQ2ia45kGocPjZ9Q@DP0c0PLtk9Qc "JavaScript (V8) – Try It Online")
---
# [JavaScript (V8)](https://v8.dev/), 69 bytes
Takes a native JSON object as input. Prints the results, using a comma as the delimiter.
```
f=(o,s)=>[o]==o||Object.keys(o).map(k=>f(o[k],k=s?s+[,k]:k,print(k)))
```
[Try it online!](https://tio.run/##nVJNS8NAEL3nVwx7SmgU0ypKIS16UVAU9CAScljTbbvdZCfubBU/8ttr0vhBbVexl4V58@bNvMfO@COnzMjS7jweLRbj2MeQgniQYBrH@PZ2dT8Tmd1V4pl8DHYLXvoqHox9TFQaqpiG1ElClfZVWBqpra@CIFiM/VcPgGleCAZ9aIq6HEtDlvWBzbgWLGzBnLfYCAWrkaqBa1BPmsGETW2RsxBYRsRSrwq8dkvgee2Omvwwly/sc8kSoRKNXYFaYrSGfQgIshJ1c8btVGZTQC1AEmRoTG0erOAFNGZAarg8OR5@HL@igmWjQbVIstZcEi7FE9yhUXAyz3PaILFkXSDBsZ6IXBCcSz1xEk8xHwkNN5ZbAbfcGGnQST6bk0UN15gpYdkaJ93gh2t6EqbJ5Jfh6quqviVYwe2Utsv/ADpwCDFsF3G05wogipydrrPT@29StdZqPOGPBLp/JxB1YQeOto/A5cZps@dq7P/X/r7zc3jtWwWLdw "JavaScript (V8) – Try It Online")
### How?
This is a recursive function walking through the keys at the root level and then in each sub-tree of the structure.
We need to process recursive calls on objects and arrays and to stop on strings and numbers. This is achieved with `[o]==o||Object.keys(o)`:
```
 type of o | [o]==o    | Object.keys(o)  | string coercion example
-----------+-----------+-----------------+-------------------------------------
 array     | false     | 0-based indices | ['foo', 'bar'] -> 'foo,bar'
 object    | false     | native keys     | {abc: 'xyz'}   -> '[object Object]'
 string    | true      | n/a             | 'hello'        -> 'hello'
 number    | true      | n/a             | 123            -> '123'
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 75 bytes
```
f=o=>Object.keys(o+''===o||o||0).flatMap(k=>[k,...f(o[k]).map(i=>k+'.'+i)])
```
[Try it online!](https://tio.run/##DchBDoMgEADA5wCRbtoeSfAHTR9gPCAurbJ1jWCTRn07NZnTjO7rkl@GOV8m7rGUYNnWz25EnyHiL0muhLDW8r6frgoCufxws4y2bqIGgCC5ia2Cz5mDrWMlQFSDalXxPCUmBOKXDHJzZlqJdGfysqL2JjhKqHsj3kjEQqNpbvre6mC241Cq/AE "JavaScript (Node.js) – Try It Online")
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~108~~ ~~146~~ ~~115~~ 92 bytes
+38 bytes to fix test cases for objects inside arrays.....
-31 bytes because we can take a parsed JSON object as input now.
-17 bytes by removing the duplicated `flat_map` usage.
```
f=->j,x=''{z=j==[*j]?[*0...j.size]:j.keys rescue[];z.flat_map{|k|[r=x+k.to_s]+f[j[k],r+?.]}}
```
[Try it online!](https://tio.run/##nZJbSwMxEIXf/RXDvhRsG9yqKMpaKoJXKlhBJASJ67TdS5M1k8Xaun/ddW1FqTWKnYfAnDk5MF9i8vvnsuwHzYO4MQ5qtekkiIOAr8eizdc3GGMxo2iCYi9mCT4TGKQwRy72J6yfSns3ktn0JXnhJhjXE2b1HYl6n8c8EQ1TbzNRFGWWW4I@P@tddlkmDSH0ro9Ou8ygfBDldA2q8h7zaOLtwbybKZRpYxekudFf0j4CkGykVTX1boZROAStECICCaE2BkMLFuUIlBxVsgI7ROgedtpeYzlLZ@9JVEXxpeHM0MUnuNUmgcM8TemHiJnrQhN01ABTJDiP1MBpPNbpAyroWWkRbqQxkTZO84nOyWoFVzpM0JK35BI/bCQVPaF5Z/Pr9eKzK75CvJG0Q1rtJbahDjsQwGqY/Q0XBN93TlrOyeZ/WVVZi3ga3wi0/ibgt6AJu6sjcGzDq/JanqjKse6mi8PWfzFsOT/J2vwsXj/2KJsmJq3eAA "Ruby – Try It Online")
[Answer]
# [Python 2](https://docs.python.org/2/), ~~122~~ ~~135~~ ~~122~~ 119 bytes
```
f=lambda d:`d`[0]in'{['and sum([[str(k)]+['%s.'%k+q for q in f(v)]for k,v in(enumerate,dict.items)['{'<`d`](d)],[])or[]
```
[Try it online!](https://tio.run/##nVJhb9MwEP2eX3GyNDlRTdWkQaDAhFqgIIH2AT5MKIo0N3FW08ZubWcbi/LbyyVFoNEFtCZKfPfu3bPu2dsfbqVVtN@X5xteLQsORXJVXKWTTCrapJSrAmxd@WlqnfHXQTZK6Zkd07P1aAelNrADqaD0b4Ksy9bsBnNfqLoShjvBCpm7sXSiskFKG/oatTO/CDKWZoE2abYvRAkLRJKtkcoBZUDH3zVqlAgGr3rUW/gNmZEkZGROEtK0hJG3GKRNm2H4jiRdxEjzvkVSG3he38E7nCxJEjOSY4yMApeQNURg9x1pM3yDnkydsI4mDeUUm@gdTSaM3tMkallDBWaoT5fdig0L32s8wIfsanlPEjhkPWK32rgH0IEYHmG/BHBfqRVWyeVK5ivQSoC0kGtjRO7ACV6B4pXofL6Yz94Qdqyit52GRZH0qNgTLsQtfNNmDfN6s7GPSPSsz9rCTF2LjbDwSarrQeIHvSmEgq8OjxguuTHS6EHyx9o6reCLztfCkSNO9sg8XNlbYTpP/tHc/s7aPxKk4m5lT/P/OYzgBZzDaRaHkyEDwnCwEg1Wpk91CrUe2sP@ciD6vwNhBM/g5ekWDE0zOOZ0qBA/dfx48HJ4h38b7CM29ab9F3sxm/4E "Python 2 – Try It Online")
Now handles an even broader class of inputs, including `lists` of `dicts`.
[Answer]
# [PHP](https://php.net/), ~~147~~ 146 bytes
```
function f($j,$t){foreach($j as$k=>$v){if(is_array($v)){echo trim($t.="$k.",'.')."\n";f($v,$t);$t=str_replace("$k.",'',$t);}else{echo$t."$k\n";}}}
```
[Try it online!](https://tio.run/##RY/RasQgEEXf9ytkEFSQfMCmaT@kLUHM2JhNNKi7UILfnhpTiA/CvWfmwKzjur99rOU3T6eT9Y4YTidJk9iMD6j0WCJRkT66d/oSmzXcxl6FoH55yWJDPXqSgl04TU0H9NGAZA0TDXw5aIvsdchamrqYQh9wnZVG/j/HKss4R6yioijkWMw571Vt@BS96wfUfkDOthspD5xaEMidnLFWxoaY4E5gUg5BXmBWZz94hNrmExbgfg7J5zU7pmUGSa5Cx3gufd8yk@XQJwpJGBPt/gc "PHP – Try It Online")
I'm sure that this is far from best solution in PHP, but I tried my junior talent. :D
```
$json = '{
    "name" : {
        "first": "jane",
        "last": "doe"
    },
    "lang" : [
        "html", 
        "css"
    ]
}';
/** We need to define a text string variable. */
$text = ''; // or keysChainString
/** Assume that our json is decoded. */
$array = json_decode($json, true);
/** 
 * Function that extract all multidimensional array keys. 
 * The result will be as:
 * - firstKey
 * - firstKey.firstSubKey
 * - firstKey.firstSubKey.firstSubSubKey
 * - firstKey.secondSubKey
 * - secondKey
 * - etc.
 */
function extractAndFormatMultidimensionalArrayKeys($array, $text){
    /** 
     * Iterate through array. 
     */
    foreach($array as $key => $value) {
        /** 
         * Check if key value is an array.
         * Echo key appended to previously declared $text variable.
         * Then make a recursive call to this function on that array.
         * After that, delete the key from text string.
         */
        if(is_array($value)) {
            echo trim($text .= "$key.", '.') . "\n";
            extractAndFormatMultidimensionalArrayKeys($v, $t);
            $text = str_replace("$key.",'',$text);
        /** 
         * If the value is not an array, echo the text concatenated with the key. 
         */
        } else {
            echo $text . "$key \n";
        }
    }
}
```
[Answer]
# [Red](http://www.red-lang.org), 159 bytes
```
func[s][r: :rejoin g: func[s m][foreach k keys-of m[print p:
r[s k]if map? t: m/:k[g r[p"."]t]if block? t[repeat n length?
t[print r[p"."n]]]]]g ""load-json s]
```
Doesn't work in TIO since `load-json` was introduced recently, but works fine in the [Red](http://www.red-lang.org) console:
[![enter image description here](https://i.stack.imgur.com/l8p2Y.png)](https://i.stack.imgur.com/l8p2Y.png)
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~39~~ 27 bytes
```
MapIndexed[Echo@#2&,#,∞]&
```
[Try it online!](https://tio.run/##fZLfSsMwFMbv9xSHDHZjB6abKNRNNxAVdYheDBm9CO3ZGtcmW5Ix0XnvU/hwvkhNUis6/7QQkkPO9/vO1xbMZFgwwxNWTnvlFVucixQfMJ2cJJk8boatoBm8vbzGrdKgNhR6cLghghVIoN13@ylX2vgDuWcCSQAkZ3UllUg2/QAarihmvvhEMlPk7l6iNXne9KOGkw4r6eWKP9bSeiGVqQ9LWu@Y0GtUFeBMrrSRAm5kMkejiUNVj1WyqlyK6uI440kGUiBwDQwSqRQmBgyyAtw4wAXYKGA0HBx9VZELp6E/nI9wDXdSzWG4ynNHI5dSw0DMMEcNF1zMvlqw7acyT1HArWEGYcyU4lL5vm3jNocqKNtkv0em/5@bhk7k@4h7sAP7NkXr/9PBln@669oo9auXoB2Hrj2TZfgbrfsTRkNow0FF@ystj/GUjlu61ZDujRrTif@f4qhxrbgwk7guhXFUvgM) This function represents JSON arrays as `List`s and objects as `Association`s. The function takes a JSON object as input and prints a set of part specifications to the standard output, each on their own line and preceded by `>>` . A part specification is a list of indices, where each index is a 1-based number or a string wrapped in `Key`. The index of a parent object is printed after those of its children. The output for the first example is:
```
>> {Key[name], Key[first]}
>> {Key[name], Key[last]}
>> {Key[name]}
>> {Key[lang], 1}
>> {Key[lang], 2}
>> {Key[lang]}
```
If the `Key` wrapper is undesirable, it can be removed using [a 36-byte function](https://tio.run/##fZLfSsMwFMbv9xSHDHZjp7abKNRVNhCV6RC9GFJ6EdqzNa5NtiRj/pn3PoUP54vUpLUy558WQnLI@X7f@dqc6hRzqllMi0mvuKLzC57gAybhaZyKsOnt7Q7xsR2MopbTdN5f36JWoVFpF3pwvCac5kigHdj9hEmlywO5pxyJAySjdSURSNaBAw1b5NOy@ExSnWf2XqwUeVkHfsNKe5X0Ysmeamk1F1LXh4Vb7yhXK5QV4FwslRYcbkQ8Q62IRVWPUTKqTPDq4jhlcQqCIzAFFGIhJcYaNNIc7DjAOJhMYDTon2yqiLnVUJ/OR7iCOyFnMFhmmaWRS6Ggz6eYoYIh49NNC6b9TGQJcrjVVCOMqZRMyLJv27jJoQrKNJkPk6r/53Y9K/J9xAPYgUOTovH/5WDLv7tv21y3XEsJt2PRtWey8H6jdX/CXA/acFTR/kqrxJSUjl261ZD29RuTsPyfIr9xLRnXYVSXvMgvPgA):
### Wolfram Language (Mathematica), 36 bytes
```
MapIndexed[Echo[#2/.Key->N]&,#,∞]&
```
The original challenge's formatting can be achieved with [a 54-byte function](https://tio.run/##fVLLTgIxFN3zFTclYeOAzoDRBEFhowYlBhbEkFk0wx2mMtNCW4IP3PsVfpw/MrYdx@CzTfq4ufecc0@bUZ1gRjWLaB538mu6vOQzvMfZ9EYyrs/G2mzzEYvjFKfVYL8xwId6d@iRBglrXtV7e3kNa7lGpX3owMmWcJohgXrXnmMmlXYXckc5Eg9ISsvITCDZdj2o2CCfu@ATSXSW2rxIKfK87bYrFjoooFdr9lhCq6WQurys/PJEudqgLAguxFppwWEkogVqRSxVMQySQWWCF4mThEUJCI7AFFCIhJQYadBIM7DtAONgXIJhv3e6iyKWFkN9KB/iBm6FXEB/naaWjVwJBT0@xxQVDIyLuxJM@blIZ8hhrKlGmFApmZCu7rtw40NhlCkyT5Wo//v2AwvytcVD2IMj46LR/6ngm37/wJb5vlsdhN@01KVmsgp@Y2v9JPMDqMNxwfaXW47GsTTt0iqatLNdiafuP4XtivuD07AMBWE7fwc):
### Wolfram Language (Mathematica), 54 bytes
```
MapIndexed[Print@StringRiffle[#2/.Key->N,"."]&,#,∞]&
```
[Answer]
# [Julia 1.0](http://julialang.org/), 57 bytes
```
!x=[(k->["$k";"$k.".*!x[k]]).(keys(x))...;]
!x::String=[]
```
[Try it online!](https://tio.run/##rVJBT8IwFL7vV7w1HjaFxQFGAxkGYqKJhoMciFl2aEbDyrZ2tl0Y/vnZlYMkbIKJPby23/f19Xuv3ZYZxX5V13YVhE7an4boKkUTHTzkXdtVmEaR6zkp2Uuncl3P8yaRZVfj8VIJyjZBGNVbCOCJxsqxQA/0WdIvBMH0CDO4LLhQLcThkN/BGJYXinImjSQ8oY1kQXbwwUUK8zLLJOq1q964hBnbkIxIeNX2O4XPPFsTBkuFFYEVFoJy0Sl@4aVUnME7j1Oi2mTRKaT7RGRTlqkKrRIaJ8AZASoBQ8yFILECRXAODOcaZqASAov57LHlAoSZ3BFxyPW7H/dne7REOVaJ/IfnQf4t6gHyfRMHJg7R@QbcwQ3c6590tromZ1dBh7yDP5ht/BmTwyaMLjDqD6APD5c4HZ3tvJ5cy1pTWWR479hbt/4G "Julia 1.0 – Try It Online")
[Answer]
# [R](https://www.r-project.org/), 114 bytes
```
f=function(x){if(is.null(n<-names(x)))n<-seq(x);unlist(Map(function(y,z)c(z,if(is.list(y))paste(z,f(y))),x,n),,F)}
```
[Try it online!](https://tio.run/##PYxBEoIwDEWvwnTVzFQvoGzduXbdKa3WKQFJq4Dj2WsKA1n9l/@SIWdXu4Qm@g7lCF/vpKcjphAkng@oW0u8BmAg@@J4Shg8RXnVvdwPJzWDkbNar5d@Aug1RctbVwDUqBCUusAvO7ko5XtVV0t2fqDIIJ4arVBV0Cs2nRVQEO@bKh6xDawIQ1S6xr69sbTVvdnFm8em@7DEk/8 "R – Try It Online")
Defines a recursive function which takes an R list, possibly named, and returns the list of names using space as a separator. Here, a named list (or sub list) corresponds to an object in JSON, and an unnamed list corresponds to an array in JSON. 
]