No Public Fields Marshal

ID

go.no_public_fields_marshal

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

reliability, suspicious

Description

Reports a json.Marshal or xml.Marshal call whose argument is a struct type that declares no exported (upper-case) fields. The reflect-based marshallers only emit exported fields, so the call produces an empty object and silently drops all the data.

Rationale

When a struct has only unexported fields, marshalling it yields {} and the intended payload never appears in the output — the fields were almost certainly meant to be exported. The check is conservative: it flags only a struct whose definition is found in the same file, that declares at least one field (an intentionally empty struct is never reported), that has no embedded field (which could promote exported fields), and whose every field is unexported.

type hidden struct { name string }
json.Marshal(hidden{})   // FLAW — no exported fields, marshals to {}

json.Marshal(Exported{}) // OK — has an exported field

Remediation

Export the fields that should be serialized by capitalising their names, and add struct tags (json:"…​") if a different wire name is needed.