toml-lang / toml

Tom's Obvious, Minimal Language

Home Page:https://toml.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Documentation and API is confusing for Atrray of Tables

kdschlosser opened this issue · comments

in the documentation located here

https://toml.io/en/v1.0.0

near the bottom it outlines how to make an Array of Tables. The following code block is used an example

[[fruits]]
name = "apple"

[fruits.physical]  # subtable
color = "red"
shape = "round"

[[fruits.varieties]]  # nested array of tables
name = "red delicious"

[[fruits.varieties]]
name = "granny smith"


[[fruits]]
name = "banana"

[[fruits.varieties]]
name = "plantain"

Then it shows what the code above would produce in JSON

{
  "fruits": [
    {
      "name": "apple",
      "physical": {
        "color": "red",
        "shape": "round"
      },
      "varieties": [
        { "name": "red delicious" },
        { "name": "granny smith" }
      ]
    },
    {
      "name": "banana",
      "varieties": [
        { "name": "plantain" }
      ]
    }
  ]
}

I am trying to understand the designed logic behind this because it doesn't conform to the way the rest of the API has been set up. Following the API for using tables the TOML used in the example should not work.

It looks like it should produce JSON that is something along the lines of

{  
  "fruits": [
    {
      "varieties": [
        { "name": "red delicious" },
        { "name": "granny smith" },
        { "name": "plantain" }
      ]
    },
    {
      "name": "apple"
      "physical": {
        "color": "red",
        "shape": "round"
      },
    },
    {"name": "banana"}
  ]
}

following the API for tables and making an array of tables you would think would be along the lines of

[[fruits]]
name = "apple"

[physical]
color = "red"
shape = "round"

[[varieties]]  # nested array of tables
name = "red delicious"

[[varieties]]
name = "granny smith"


[[fruits]]
name = "banana"

[[varieties]]
name = "plantain"

that would form the output in which is indicated keeping with the table API

or even this would produce the same output as well.

[[fruits]]
name = "apple"
physical.color = "red"
physical.shape = "round"

[[varieties]]  # nested array of tables
name = "red delicious"

[[varieties]]
name = "granny smith"


[[fruits]]
name = "banana"

[[varieties]]
name = "plantain"

There is no bug in the spec example; the corresponding JSON is correct. To me it seems that the missing link is your understanding of how table nesting works in TOML.

Each set of [] and/or [[]] begins a new section of the document, with no hierarchical relationship to any other that came before. Instead nesting is expressed by fully-qualified names. For example, for physical to be a sub-table of fruits, it must be fully-qualified as [fruits.physical], not simply listed after [fruits]. This means that non-inline tables can be expressed any order.

Arrays-of-tables work much the same way, in that they require fully-qualified names for nesting, with the additional caveat that ordering is imposed between elements of the same array (i.e elements with the same fully-qualified name) such that each new appearance in [[]] begins the next element in the array.

Does that help? If not, I'm not clear on where you're tripping up here. I readily acknowledge that the arrays-of-tables syntax is a bit counter-intuitive initially.

I guess what I am not understanding is how it is determined what tables there are and are not.

if was declared that there is an array of tables named fruits [[fruits]]

That equates to a JSON output of

{
  "fruits": [
    {},
    {},
    ...
  ]
}

then it is declared that the tables inside of the array have a subtable of "physical" but that subtable only shows up in a single table in the array and not all of them...

How is it determined that new table declarations end??

if I wanted the JSON to be as follows

{
  "fruits": [
    {
      "name": "apple",
      "physical": {
        "color": "red",
        "shape": "round"
      },
      "varieties": [
        { "name": "red delicious" },
        { "name": "granny smith" }
      ]
    },
    {
      "varieties": [
        { "name": "plantain" }
      ]
    }
  ]
}

would it be doing this?

[[fruits]]
name = "apple"

[fruits.physical]  # subtable
color = "red"
shape = "round"

[[fruits.varieties]]  # nested array of tables
name = "red delicious"

[[fruits.varieties]]
name = "granny smith"


[[fruits.varieties]]
name = "plantain"

That doesn't seem right. how would I go about adding a new table to the array and that new table has a single element in in and that element is another array??

Or if I wanted to specify the "name" table entry after the varieties?? If I specified the name element after specifying the varieties then it would assume the name element belongs to the varieties array and not the fruits array.

[[fruits]]
[[fruits.varieties]]
name = "plantain"

name="banana"

is that correct???

[[fruits]]
[[fruits.varieties]]
name = "plantain"

[[fruits]]
name="banana"

I don't think that is right...

or does it specifically have to be ordered in such a way that any declarations of nested tables or arrays MUST happen after other table entries are made??

The only thing stated in the API is "Any reference to an array of tables points to the most recently defined table element of the array. " There is no mention of defining an array of tables prior to adding a standard table entry. If I was to point to the array of tables again in order to add that standard table entry a new table would be made in the array.

I am thinking that the order in which items are added to the table in the array is very specific and not like the rest of the API.

as an example.

[some_table]
var1 = ""
var2 = ""

[some_table.subtable]
svar1 = ""
svar2 = ""

[another_table]
avar1 = ""
avar2 = ""

[some_table.subtable]
svar3 = ""
svar4 = ""

[some_table]
var3=""
var4=""

would produce the following JSON

{
    "some_table": {
        "var1": "",
        "var2": "",
        "subtable": {
            "svar1": "",
            "svar2": "",
            "svar3": "",
            "svar4": ""
        },
        "var3": "",
        "var4": ""
    },
    "another_table": {
        "avar1": "",
        "avar2": ""
    }
}

also if I wanted to add a subtable to one of the tables in the varieties array??

is it done like so?

[[fruits]]
name = "apple"

[[fruits.varieties]]  # nested array of tables
name = "red delicious"

[[fruits.varieties]]
name = "granny smith"

[fruits.varieties.physical]
color = "red"
shape = "round"

How is it determined that new table declarations end??

When a new table declaration begins, e.g.

[a] # all the key-value pairs after this line belong to 'a', until a new [] or [[]] appears
foo = "bar" # foo is a child of 'a'

[b] # this ends 'a', and stars 'b'
foo = "bar" # _this_ foo is a child of 'b'

Or if I wanted to specify the "name" table entry after the varieties?? If I specified the name element after specifying the varieties then it would assume the name element belongs to the varieties array and not the fruits array.

I don't think that is right...

Or if I wanted to specify the "name" table entry after the varieties??

If you want a general name for a fruit, with variety sub-tables that each have their own specific variety name, then you'd need to specify the general name directly under the [[fruits]] element for that 'class' of fruit, then give each variety a name in their respetive sub-table, e.g.:

[[fruits]]            # fruits[0]
name = "banana"       # fruits[0].name

[[fruits.varieties]]  # fruits[0].varieties[0]
name = "plantain"     # fruits[0].varieties[0].name

[[fruits]]            # fruits[1]
name = "apple"        # fruits[1].name

[[fruits.varieties]]  # fruits[1].varieties[0]
name = "granny smith" # fruits[1].varieties[0].name

[[fruits.varieties]]  # fruits[1].varieties[1]
name = "pink lady"    # fruits[1].varieties[1].name

[[fruits]]            # fruits[2]
name = "pear"         # fruits[2].name

For the rest of your queries it's probably easier for you to learn-by-doing using a tool like this.

Looks like there isn't more to discuss here. :)