TYSON support, and is forward compatible, with any user-defined types. These user-defined types can come from any external environment, specification or language.
TYSON does not restrict the definition of types in any way, except that any user-defined types MUST fulfill the general guidelines set out in sections 2.1, 2.2 and 2.3. These restrictions were designed to ensure soundness of the syntax and of its semantics, while being as little restrictive as reasonably possible, and correspond to established practice:
The type name must correspond to a JSON string, but different from all builtin types, which are reserved.
The user-defined type MUST have a clearly documented value space.
If it is not an atomic type, its value space MUST be either a set of objects, or a set of arrays.
If it is an atomic type, it MUST also have a clearly documented lexical space and lexical mapping.
Important remark
While users of TYSON may support types obtained by the union of other types, type annotations used in a TYSON document MUST NOT use union types that do not fulfill the above criteria, because this leads to ambiguities in the lexical mappings. For example, the union type containing all strings and booleans MUST NOT be used as a TYSON type annotation. Any value in the corresponding value space must be either annotated as string, or as boolean, so that the typed values are non ambiguous. For example, ("string-or-boolean") "true" would be ambiguous and is not allowed, while ("string") "true" and ("boolean") "true" are not.
The TYSON specification enforces correctness of its builtin types.
An object MUST be annotated with either "object" or a user-defined type.
An array MUST be annotated with either "array" or a user-defined type.
If an atomic value is annotated with a builtin type, then this builtin type MUST be atomic, and the syntactic representation of this value MUST belong to the lexical space of the builtin type.
Quotes MUST be ignored for the purpose of checking lexical values.
Examples of non-well-formed TYSON (they MUST be refused by a conforming processor)
("boolean") "yes"
("yes" is not in the lexical space of the boolean builtin type)
("integer") { "foo" : "bar" }
(An object is not in the value space of the integer builtin type)
("array") { "foo" : "bar" }
(An object is not in the value space of the array builtin type)
("integer") "foo"
("foo" is not in the lexical space of the integer builtin type)
("integer") "2.0"
(TYSON is lightweight and does NOT do any casts, it only looks at whether the lexical value is in the lexical space of the annotating type, which is not the case here)
("object") true
(true is not an object)
A conformant TYSON processor MUST accept any user-defined type annotation on any value. A TYSON document annotating all its values with non-builtin type names is thus always considered well-formed from the perspective of this specification, assuming the other syntactic constraints are fulfilled.
Whether the annotated atomic values in a TYSON document belong to the lexical space of a user-defined type is outside of the scope of this specification, and is the responsibility of consuming applications to enforce their additional constraints.
Whether the annotated objects or arrays in a TYSON document belong to the value space of a user-defined type is outside of the scope of this specification, and is the responsibility of consuming applications.
The format in which types are documented is outside of the scope of this specification. Looking up type documentation given a TYSON document is outside of the scope of this specification.
Example of well-formed TYSON (they MUST be accepted by a conforming processor, leaving further decisions involving validity against user-defined types to the consuming application)
("my-array") { "foo" : "bar" }
(TYSON does not enforce validation of user-defined types)
("boolean") "true"
(TYSON ignores quotes if an annotation is present: the string "true" is mapped to the boolean value true via the lexical mapping of the boolean builtin type)
("string") false
(This is the string "false", the unquoted literal false being interpreted as a lexical value)
("string") null
(This is the string "null", the unquoted literal null being interpreted as a lexical value)
("integer") "2"
(The string "2" is mapped to the integer value 2 in the lexical mapping of the integer builtin type)
A conforming TYSON processor MUST hide from the consuming application whether an annotated lexical value was quoted or not.
For example, the following three TYSON annotated-values MUST be exposed in the same way to the consuming application: as the boolean value true.
true
("boolean") true
("boolean") "true"