In a Helm chart template, what do `toYaml`, `fromYaml` and `toJson` do?
answer
- Structure in, text out, and back again
- The output starts at column zero
- One of them fails quietly and returns a key
- JSON is legal YAML, which buys a single line
- Whatever the user wrote reaches the object
basics
~20 sThey convert between structured values and text inside a Helm template. toYaml serialises any values subtree to a YAML string the caller must indent; fromYaml parses a YAML string back into a map; toJson emits compact JSON, which is also valid YAML.
solid answer
~50 s`toYaml` is how a chart splats a whole values subtree into a manifest without enumerating its fields — `{{ toYaml .Values.resources }}` emits YAML with no leading indentation and no trailing newline, so the caller supplies the indentation before it lands in the document. `fromYaml` goes the other way, turning a YAML string — typically a config blob a user passed as a value — into a map the template can index. `toJson` (and `toPrettyJson`) serialise to JSON; because JSON is a subset of YAML, `toJson` output drops onto one line, which is why it is the usual choice for an annotation value where multi-line indentation would be awkward. The trade-off with `toYaml` is that whatever the user put in the map reaches the object verbatim — the chart validates nothing unless a values schema does it.
code
yaml · 4 linespodAnnotations:
fanout.routes/table: {{ toJson .Values.fanout.routes | quote }}
resources:
{{ toYaml .Values.resources | indent 2 }}go deeper
Recall what each one converts: a values subtree to YAML text, YAML text back to a map, and a structure to compact JSON. Knowing that toYaml output has to be indented by the caller is the point interviewers check first.
Explain the mechanics and the quiet failures: toYaml returning an empty string on a marshal error, fromYaml returning an Error key instead of failing, and why compact JSON is safe to inline in a YAML document.
Show the trade-off you are accepting when a chart splats an opaque map: unvalidated user structure reaching live objects, and rendered blobs stored with every release revision. Be ready to say when you would model fields explicitly instead.
Own the design line between an opaque pass-through and a modelled values contract. Splatting maximises flexibility and minimises chart maintenance, but it moves validation to the API server and makes the chart's real surface undocumented.
### Why a chart needs serialisation functions at all A Helm template produces text, but values arrive as structured data: maps, lists, numbers, booleans. The moment a chart wants to hand a user-supplied *structure* to a rendered object — a resources block, a node selector, a set of annotations, a whole application config file — it needs a function that turns that structure back into YAML or JSON. That is the family: `toYaml`, `fromYaml`, `toJson`, `toPrettyJson`, plus the array variants `fromYamlArray` and `fromJsonArray`. They are Helm additions rather than parts of the Go template language. ### `toYaml` `{{ toYaml .Values.resources }}` marshals whatever it is given — map, list or scalar — into a YAML string. Two properties define how it is used: 1. **It emits no leading indentation.** The output starts at column zero regardless of where the call appears in the document, so the caller has to indent it to the position the surrounding YAML expects before the result is inserted. This is why `toYaml` almost never appears alone in a real chart; it is always the first stage of a pipeline whose last stage fixes the indentation. 2. **It strips the trailing newline**, so it slots into a document without leaving a stray blank line behind. The reason charts reach for it is leverage. A chart that wants to support the full resources structure has two choices: enumerate every field (`limits.cpu`, `limits.memory`, `requests.cpu`, `requests.memory`, and the ones added next year), or accept an opaque map and serialise it. `toYaml` is the second choice, and it is the reason most published charts let you set arbitrary `nodeSelector`, `tolerations`, `affinity` and `podAnnotations` without the chart author having modelled any of it. That leverage has a price. Anything the user puts in that map reaches the rendered object exactly as written, including a misspelled field name that the chart cannot catch — the API server rejects it later, or worse, silently ignores it. A `values.schema.json` is the only thing that puts a guard in front of a splatted map. There is a second, quieter failure: if the value cannot be marshalled, `toYaml` yields an empty string rather than an error, so the field simply disappears from the manifest. When a block you expected has vanished from `helm template` output, an unmarshallable value is one of the candidates. ### `fromYaml` `fromYaml` is the inverse: hand it a YAML string and it returns a map you can index. The common source is a config blob a user passed as a single string value, or a file the chart ships and reads. Typical shape: ```yaml {{- $cfg := .Values.fanout.rawConfig | fromYaml }} maxInFlight: {{ $cfg.maxInFlight | default 384 }} ``` The important behaviour is its error handling: when the string does not parse, `fromYaml` does **not** fail the render. It returns a map carrying an `Error` key describing the parse failure. A template that indexes straight into the result then renders an empty value and produces a manifest that is structurally valid and semantically wrong. If a chart genuinely depends on parsing user-supplied YAML, it should check for that key and call `fail` with a message that names the value, rather than letting the empty result through. `fromYamlArray` is the variant for a document whose top level is a list. ### `toJson` and `toPrettyJson` `toJson` serialises to compact JSON on a single line; `toPrettyJson` indents it for readability. The reason `toJson` earns its place in charts is a YAML fact rather than a Helm one: JSON is a subset of YAML, so compact JSON output is a legal YAML scalar structure that needs no indentation work at all. Where a value has to sit inline — an annotation's value, a field that must be a string, a compact representation the consuming application will parse itself — `toJson` avoids the whole multi-line indentation problem that `toYaml` creates. ### Choosing between them Use `toYaml` when the output *is* part of the manifest's structure: a block of fields the API server will read as YAML. Use `toJson` when the output is a *value* — something that must be a single scalar, typically a string, and often quoted. Use `fromYaml` only where a chart really must inspect user-supplied YAML, and check the `Error` key when you do. One operational consequence is easy to forget: the rendered manifest is not only applied, it is also kept with the release record. A batch-job chart that serialises a large config blob into a ConfigMap carries that blob into every stored revision too — a 1.1 MiB config splatted with `toYaml` is 1.1 MiB in the object *and* in the release's stored manifest, revision after revision, even though Helm compresses what it stores. Splatting large data through these functions is convenient; keeping several megabytes of it in release history is a decision, not an accident.
- What does `fromYaml` do when the string it is given is not valid YAML?It does not fail the render. It returns a map containing an `Error` key whose value describes the parse failure, so a template that indexes into the result gets empty values and produces a manifest that looks fine and is wrong. If a chart parses user-supplied YAML, test for that key and call `fail` with a message naming the value, so the problem surfaces at render time rather than in a running pod.
- A block rendered with `toYaml` is missing entirely from `helm template` output. What are the candidates?Either the source value is empty — an absent key, or a `with` block that collapsed — or the value could not be marshalled, in which case `toYaml` returns an empty string rather than raising an error. Check the merged values first with `helm get values` for a live release or by rendering with the same files, then narrow to the template line by rendering just that file.
- Why do charts embed a structure as `toJson` output rather than `toYaml` inside an annotation?An annotation value must be a single string, and JSON is a subset of YAML, so compact `toJson` output is one line that needs no indentation handling and quotes cleanly. `toYaml` would emit a multi-line block that has to be indented into position and cannot sit where a scalar is required. `toPrettyJson` exists when a human will read the value, at the cost of multi-line output.
saying these in an interview costs you the question
- Believing toYaml indents its output to the call site
- Expecting fromYaml to fail the render on bad input
- Thinking toJson output is invalid inside a YAML document
- Assuming a splatted map is validated by the chart
- Saying toYaml is a Go template builtin
- Ignoring that rendered blobs are kept with the release record