Components
An open model needs flexibility in its values as well as its field names. A field might hold a boolean, a number, or a collection of related information. JSON allows each object member to hold any JSON value, including another object or an array. Supporting additional types in Stardust needs to allow those same combinations.
A field can hold a primitive value, an object, or an array. For example, an invoice's reason can be text and its items an array of objects. Neither field needs a type declaration before the application records it. A selected schema can restrict the values an operation accepts.
Explicit types
An invoice also contains values whose meaning needs more than JSON's primitive types. Its recipient is a reference to another entity, its due date is an instant, and its payment period is a duration. Representing all of these as ordinary strings or numbers leaves each reader to reconstruct those distinctions. Explicit types keep them in the value itself.
These types fit into the same model as primitive values and collections. A collection can contain entity references or durations alongside ordinary text and numbers. The field's name and the entity's tags provide context, while the value's type distinguishes a reference from a quantity or text. Moving the data between application languages can keep those distinctions without making one language's classes the shared definition.
A small vocabulary supplies types used across many domains, including references and instants. Custom tagged values let applications add types for their own domain. For example, a money value can carry a currency and an amount together. The application supplies the rules for using that value, including which currencies can participate in a calculation.