The mapping from Terraform native syntax to JSON is described in more detail in the JSON Configuration Syntax documentation. The relevant section for this question is Nested Block Mapping; although in this case the
provider block isn’t “nested” in the sense of being inside another block, in practice the rules for processing blocks are the same at all nesting levels.
The usage of
provider blocks with
alias set is similar to
provisioner blocks inside
resource where often the block labels alone are not sufficient to make the JSON property name unique, and so indeed you can use the array-of-objects form shown in your first example with
provider blocks, similarly to what is shown for
provisioner blocks in the documentation.
This syntax generalizes for anything defined as being a nested block in the native syntax. For example, you could write
variable blocks that way too, even though it’d be unnecessary in that case because they have unique labels by definition:
This is a situation where we’re representing a concept that doesn’t exist in JSON, so Terraform’s configuration decoder is using its knowledge that
variable are all defined to be block types in their respective contexts and using this more liberal/flexible processing model to strike a compromise between conveniently representing simple cases where the labels are unique while still being able to handle the more complex cases like yours using common JSON tools.
Giving a totally invalid value for the
"provider" property causes Terraform to produce an error message that betrays a bit how it’s processing this:
Error: Incorrect JSON value type
on json-blocks.tf.json line 2:
2: "provider": "invalid"
Either a JSON object or JSON array of objects is required here, to specify
name labels for this block.
Whenever the property name is specified as being a block type rather than an attribute, the decoder will check to see if the given property value is either a JSON object or JSON array, and it will then traverse that value to go looking for label keys, either by looking directly at the given object properties or by iterating over the array and looking at the properties of each nested object in turn.
Since Terraform is just scanning over the contents anyway, it can and will accept duplicate property names if they describe something that’s valid per the Terraform language schema, but indeed most software generating JSON cannot produce such a thing and so the array-of-objects form is easier to produce programmatically.