Access a map value using a variable key in a Go template
Asked Answered
J

2

110

How can I look up the value of a map by using a variable key without iterating?

So one can lookup a constant key on variable map $x with $x.key1, but is it possible to do amap.$key?

Jiggle answered 1/10, 2014 at 23:5 Comment(0)
I
200

You use the index function:

{{index .Amap "key1"}}
index
    Returns the result of indexing its first argument by the
    following arguments. Thus "index x 1 2 3" is, in Go syntax,
    x[1][2][3]. Each indexed item must be a map, slice, or array.

https://golang.org/pkg/text/template#hdr-Functions

Innate answered 1/10, 2014 at 23:9 Comment(11)
This works, I had tried it but was using it with a slice when I thought I was using it with a map.Jiggle
@KyleBrandt I wrote the answer then I actually had to double check to make sure.Innate
Does this work inside a pipeline? Can you give an example of how to use this as part of {{template "name" how_to_index_here?}}Identification
@chakrit: Yes, wrap the pipeline in parens: {{template "name" (index .Amap "key1")}} It should be noted that the simpler syntax of accessing map keys directly from dot also works: {{template "name" .Amap.key1}}Stoltz
Is it also possible if the resulting value is a struct to select a field? {{index .Amap "key1"}}.MyfieldCupriferous
@GertCuykens after searching for exactly that answer all day and coming up with nothing, here is what I figured out: {{ with (index .Amap "key1") }}{{ .Myfield }}{{ end }}Adham
@JoeLinux, that's a great solution. Works well with keys that are more than alphanumeric, e.g. {{ with (index .Amap "key-with-hyphens") }} {{ .Myfield }} {{ end }}Seasonal
Note both args can be variables: {{ index .Amap .var2.username }} and if you want a specific child of the result (say Amap[var2.username] is itself yaml instead of a value), you can use {{ (index .Amap .var2.username).some_field }}Costermansville
Thanks this works for getting a key with dots, e.g. "{{index .data "key.with.dots"}} kubectl get configmap myMap --template='{{index .data "foo.bar"}}Fomentation
If i have a $var holding a field name. will .Values.mykey.($var) or .Values.mykey.(index .Amap "var") work ?Miss
Adding a note here for folks using packer. We wanted to add a tag to a new AMI that would indicate the source AMI of the source AMI. We know the source AMI is tagged with "source-ami-id", and we can access the .SourceAMITags, but I wasn't sure how to access this particular tag, since its key has "-" in it. Packer uses golang templates, so I was able to make it work with this syntax: tags = { "upstream-source-ami-id" = "{{ index .SourceAMITags \"source-ami-id\" }}" }Octavus
Q
17

A simpler way would be to do: {{.Amap.key1}}. However, this will only work if the key is alphanumeric. If not, you'll need to access it using index.

From the documentation:

- The name of a key of the data, which must be a map, preceded
  by a period, such as
    .Key
  The result is the map element value indexed by the key.
  Key invocations may be chained and combined with fields to any
  depth:
    .Field1.Key1.Field2.Key2
  Although the key must be an alphanumeric identifier, unlike with
  field names they do not need to start with an upper case letter.
  Keys can also be evaluated on variables, including chaining:
    $x.key1.key2
Quevedo answered 11/8, 2020 at 15:27 Comment(2)
This is very use full while the template is a JSON text. For JSON text, to keep syntax ok, the form of {{index .Amap "key1"}} must write as {{index .Amap \"key1\"}} in string value, and the latter format not working under template.Odont
At first I thought that the alphanumeric limitation was inconsequential. Who would use non alphanumeric characters in map names. And then I realized that _ technically does not count as alphanumeric.Uncle

© 2022 - 2024 — McMap. All rights reserved.