Targets · JSON · Naming considerations

Naming considerations

A Program name nests to any depth — Ui.Button.Integer.Increment. This page is how that dotted name is carried into the JSON form, which is the one place it is kept exactly as written.

Contents

JSON is the canonical command form every module is stored in — the interchange the other targets render from, not a language you run. These pages describe that form.

How it looks

The JSON stores the dotted name as a single string, exactly as it was written — no case change, no separator swap, no escaping.

{ "op": "call", "name": "Ui.Button.Integer.Increment", "args": ["count"] }

The natural idiom

The JSON is a data record, not a namespace, so there is nothing to nest a name into. The idiomatic thing is simply to keep the canonical name as its own field — the whole point of the form is to be the single, unambiguous record of what the program said, so every other target can reconstruct its own idiom from it.

Keeping the real dotted name

Because the name is stored verbatim in a string field, no dotted access is ever “faked” — there is nothing to fake. Resolution happens later: when the JSON is rendered to a target, that target's rules decide whether the path becomes a nested object (JavaScript), an underscore join (Go), a :: path (Rust), and so on. The JSON keeps the source of truth; each target munges its own copy.

{
  "node": "native",
  "name": "Network.Web.Client.Post",
  "returns": "Network.Web.Response",
  "inputs": [ { "type": "App.Profile", "name": "profile" } ]
}

Recommendation

Store the name verbatim — and never munge it here. The JSON form is deliberately the one target that performs no renaming: it neither snake-cases, nor joins, nor escapes reserved words (it has none). Every collision and convention is a rendering concern, resolved on the target that has the collision — keeping the interchange lossless and each target free to choose its own idiom.