Skip to content

Commit d6b4076

Browse files
committed
instance validator update
Signed-off-by: Clemens Vasters <clemens@vasters.com>
1 parent 57a03f3 commit d6b4076

File tree

2 files changed

+90
-108
lines changed

2 files changed

+90
-108
lines changed

json-structure-primer.md

Lines changed: 89 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# JSON Structure Primer
22

3-
> Author: Clemens Vasters, Microsoft, February 2025, clemensv@microsoft.com
3+
> Author: Clemens Vasters, Microsoft, February 2025, <clemensv@microsoft.com>
44
55
This primer introduces _JSON Structure_, a modern, strictly typed data
66
definition language that resembles JSON Schema, but has very different basic
77
design principles.
88

99
JSON Structure focuses on defining data types with clear, deterministic
1010
constraints while supporting extensions for precise representations of numbers,
11-
dates, and more.
11+
dates, and more.
1212

1313
Common programming language concepts like reuse and composition are supported
1414
directly in the schema language, but while avoiding introduction of the entire
@@ -66,14 +66,59 @@ This approach better supports code generation, database mappings, and
6666
integration with modern programming languages, while keeping the validation
6767
capabilities as optional extensions for those who need them.
6868

69-
## 2. Key Concepts
69+
## 2. Design Principles
70+
71+
JSON Structure is designed with the following principles in mind:
72+
73+
- **Scope**: JSON Structure "Core" is meant to be a sufficient language for a
74+
"schema first" approach to defining application data structures in "polyglot"
75+
environments where such definitions are shared across application modules and
76+
tiers and databases and caches and other data stores. It is not a goal to be
77+
able to capture, say, all intricacies of a C++ class and express those. In
78+
that way, JSON Structure definitions are meant to be authoritative. Tools
79+
should be able to map from JSON Structure to programming language constructs
80+
and, within reasonable bounds, to database structures without losing
81+
structural information, but the reverse might not always be true.
82+
- **Relation to JSON**: JSON Structure is expressed in JSON and has built-in
83+
rules for how types are mapped to JSON encoding, but the data definitions can
84+
be seen as being independent of JSON. You can declare an _object_ type in JSON
85+
Structure and use that type to code-generate a record class for an
86+
Object-Relational-Mapping framework and a corresponding database table without
87+
JSON encoding ever playing a role.
88+
- **Familiarity**: Millions of software developers recognize declarations of the
89+
shape _"type":"object", "properties": {...}_ as what a "schema" should look
90+
like and it's often the only formal schema model they a have encountered. In
91+
spite of its shortcomings as a data definition language, JSON Schema's most
92+
basic expressions for to declare a type are etched into people's minds and
93+
any improvement that does not pick people up from where they are´will have
94+
it harder to gain substantial traction.
95+
- **Simplicity**: JSON Structure is designed to be simple and easy to
96+
understand. The schema language is designed to be easy to read and write, with
97+
a focus on clear and concise definitions. The type system is meant to easily
98+
align with concepts people use and need in their programming and database
99+
work, including safe numeric expressions and date and time expressions.
100+
- **Pragmatism**: JSON Structure is designed to be a pragmatic data definition
101+
language for application developers and not a language for metadata geeks.
102+
That means that when there is tension between providing type definitions for
103+
application use-cases and being able to describe or validate any imaginable
104+
JSON expression, the application use-cases win.
105+
- **Optional Complexity**: JSON Structure "Core" documents are always
106+
self-contained and simple to understand and process. If the user needs further
107+
capabilities like imports of definitions from external files, semantic
108+
annotations, or complex validation hints, they can opt into those by using
109+
companion specifications, potentially at the expense of compatibility with
110+
implementations of JSON Structure that are restricted to the "Core"
111+
specification.
112+
113+
## 3. Key Concepts
70114

71115
JSON Structure is designed to look and feel very much like the JSON Schema
116+
72117
drafts you already know, but some rules have been tightened up to make it easier
73118
to understand and use. Therefore, existing JSON Schema documents may need to be
74119
updated to conform to the new rules.
75120

76-
### 2.1. Differences to JSON Schema Drafts
121+
### 3.1. Differences to JSON Schema Drafts
77122

78123
- **Strict Typing:** Every schema must explicitly specify its data type. For
79124
compound types (objects, arrays, sets), additional required metadata like a
@@ -88,18 +133,18 @@ updated to conform to the new rules.
88133
format-specific data.
89134
- **Compound Types:** The compound types have been extended to include `set`,
90135
`map`, and `tuple`
91-
- **Object:** Define structured data with a required `name` and a set of
136+
- **Object:** Define structured data with a required `name` and a set of
92137
`properties`.
93-
- **Array:** List of items where the `items` attribute references a declared
138+
- **Array:** List of items where the `items` attribute references a declared
94139
type without inline compound definitions.
95-
- **Set:** An unordered collection of unique elements.
96-
- **Map:** A collection of key-value pairs where keys are strings and values
140+
- **Set:** An unordered collection of unique elements.
141+
- **Map:** A collection of key-value pairs where keys are strings and values
97142
are of a declared type.
98-
- **Tuple:** A fixed-length array of elements where each element is of a
143+
- **Tuple:** A fixed-length array of elements where each element is of a
99144
declared type. It's a more compact alternative to objects where the
100145
property names are replaced by the position in the tuple. Arrays or maps
101146
of tuples are especially useful for time-series data.
102-
- **Choice:** A discriminated union of types, where one of the types is
147+
- **Choice:** A discriminated union of types, where one of the types is
103148
selected based on a discriminator property. The `choice` keyword is used
104149
to define the union and the `selector` property is used to specify the
105150
discriminator property.
@@ -113,7 +158,7 @@ updated to conform to the new rules.
113158
`$import` keyword from the optional [import][JSTRUCT-IMPORT] spec to import
114159
the types you need. Once imported, you can reference types with `$ref`.
115160

116-
### 2.2. Extensibility Model
161+
### 3.2. Extensibility Model
117162

118163
JSON Structure is designed to be extensible. Any schema can be extended with
119164
custom keywords given that those do not conflict with the core schema language
@@ -125,7 +170,7 @@ custom keywords, but it's recommended to do so.
125170
JSON Structure is designed to be modular. The core schema language is defined in
126171
the [JSON Structure Core][JSTRUCT-CORE] document. Companion specifications
127172
provide additional features and capabilities that can be used to extend the core
128-
schema language.
173+
schema language.
129174

130175
The `abstract` and `$extends` keywords enable controlled type extension,
131176
supporting basic object-oriented-programming-style inheritance while not
@@ -135,7 +180,7 @@ issues between JSON schemas, programming types, and databases.
135180

136181
There are two types of formal extensions: _extensible types_ and _add-in types_.
137182

138-
#### 2.2.1. Extensible Types
183+
### 3.3. Extensible Types
139184

140185
It's fairly common that different types share a common basic set of properties.
141186
In JSON Schema itself, the `description` property is a good example of a
@@ -185,7 +230,7 @@ Example:
185230
}
186231
```
187232

188-
#### 2.2.2. Add-in Types
233+
### 3.4. Add-in Types
189234

190235
Add-in types allow modifying any existing type in a schema with additional
191236
properties or constraints. Add-ins are offered to the instance document author
@@ -248,7 +293,7 @@ set of add-in names that are applied to the schema for the document.
248293
}
249294
```
250295

251-
### 2.3. Reusing Types across different Schema Documents
296+
### 3.5. Reusing Types across different Schema Documents
252297

253298
The prior versions of JSON Schema in effect allowed for `$ref` to reference
254299
arbitrary JSON nodes from the same or external document, which made references
@@ -257,11 +302,11 @@ deep links into external schema documents and/or schema documents were
257302
cross-referenced using relative URIs to avoid committing to an absolute schema
258303
location.
259304

260-
JSON Structure has a more controlled approach to limit that complexity.
305+
JSON Structure has a more controlled approach to limit that complexity.
261306

262307
1. The `$ref` keyword can only reference named types that exist within the
263308
same document. It can no longer reference and insert arbitrary JSON nodes
264-
and it can no longer reference external documents.
309+
and it can no longer reference external documents.
265310
2. To reuse types from other documents, you now need to use the `$import`
266311
keyword from the optional [import][JSTRUCT-IMPORT] spec to import the types
267312
you need into the scope of the schema document. Once imported, you use the
@@ -272,7 +317,7 @@ JSON Structure has a more controlled approach to limit that complexity.
272317
with local definitions by explicitly declaring a type with the same name
273318
and namespace as as the imported type.
274319

275-
### 2.4. Core and Companion Specifications
320+
### 3.6. Core and Companion Specifications
276321

277322
The following documents are part of this JSON Structure proposal:
278323

@@ -291,7 +336,7 @@ The following documents are part of this JSON Structure proposal:
291336
- [JSON Structure Import][JSTRUCT-IMPORT]: Defines a mechanism for importing
292337
external schemas and definitions into a schema document.
293338

294-
### 2.5. Meta-Schemas
339+
### 3.7. Meta-Schemas
295340

296341
Meta-schemas are JSON Structure documents that define the structure and
297342
constraints of schema documents themselves. Meta-schemas do not have special
@@ -325,11 +370,11 @@ of the extended meta-schema is
325370
The ["validation" meta-schema](./json-schema-metaschema-validation.json) enables
326371
all add-ins defined in the extended meta-schema.
327372

328-
## 3. Using Structure Core
373+
## 4. Using Structure Core
329374

330375
This section introduces JSON Structure by example.
331376

332-
### 3.1. Example: Declaring a simple object type
377+
### 4.1. Example: Declaring a simple object type
333378

334379
Here is an example of a simple object type definition:
335380

@@ -358,7 +403,7 @@ required and no longer implied to be `object` if not present. You may also
358403
notice that the "dateOfBirth" property uses the new `date` type, which is an
359404
extended native type.
360405

361-
### 3.2. Example: Declaring Primitive and Extended Types
406+
### 4.2. Example: Declaring Primitive and Extended Types
362407

363408
Below is an example schema that defines a simple profile with a few more
364409
extended types:
@@ -385,7 +430,7 @@ The `decimal` type is another extended type that represents a decimal number
385430
with a specified precision and scale. The `datetime` type is an extended type
386431
that represents a date and time value.
387432

388-
## 4. Example: Declaring inline compound types
433+
## 5. Example: Declaring inline compound types
389434

390435
This is an example of a type that is declared inline. This is useful for
391436
compound types that are not reused elsewhere in the schema. The `address`
@@ -420,7 +465,7 @@ type cannot be referenced from other types in the schema.
420465
}
421466
```
422467

423-
### 4.1. Example: Declaring reusable types in `definitions`
468+
### 5.1. Example: Declaring reusable types in `definitions`
424469

425470
To define reusable types, you can use the `definitions` keyword to define types
426471
that can be referenced by other types in the same document. Here is an example:
@@ -461,7 +506,7 @@ Mind that the `$ref` keyword can now only reference types declared in the
461506
`definitions` section of the same document. The keyword can only be used where a
462507
type is expected.
463508

464-
### 4.2. Example: Structuring types with namespaces
509+
### 5.2. Example: Structuring types with namespaces
465510

466511
Namespaces are used to scope type definitions. Here is an example of how to use
467512
namespaces to structure your types, with two differing `Address` types:
@@ -504,7 +549,7 @@ namespaces to structure your types, with two differing `Address` types:
504549
}
505550
```
506551

507-
### 4.3. Example: Using an Array Type
552+
### 5.3. Example: Using an Array Type
508553

509554
This example shows how to declare an array of strings, which is not much
510555
different from defining an object:
@@ -558,7 +603,7 @@ To declare an array of a reusable type, you can use the `$ref` keyword:
558603
}
559604
```
560605

561-
### 4.4. Example: Declaring Maps
606+
### 5.4. Example: Declaring Maps
562607

563608
This example shows how to declare a map of strings to `Color` objects:
564609

@@ -580,7 +625,7 @@ This example shows how to declare a map of strings to `Color` objects:
580625
}
581626
}
582627
}
583-
```
628+
```
584629

585630
Instance data for this schema might look like this:
586631

@@ -595,7 +640,7 @@ Instance data for this schema might look like this:
595640
}
596641
```
597642

598-
### 4.5. Example: Declaring Sets
643+
### 5.5. Example: Declaring Sets
599644

600645
This example shows how to declare a set of strings:
601646

@@ -614,7 +659,7 @@ elements. The schema above would match the following instance data:
614659
["apple", "banana", "cherry"]
615660
```
616661

617-
### 4.6. Example: Declaring Tuples
662+
### 5.6. Example: Declaring Tuples
618663

619664
Tuples are fixed-length arrays with named elements, declared via the `tuple` keyword.
620665

@@ -637,11 +682,11 @@ An instance of this tuple type:
637682
["Alice", 30]
638683
```
639684

640-
### 4.7. Example: Declaring Choice Types
685+
### 5.7. Example: Declaring Choice Types
641686

642687
Choice types define discriminated unions via the `choice` keyword. Two forms are supported:
643688

644-
#### Tagged Unions
689+
### 5.8. Tagged Unions
645690

646691
Tagged unions represent the selected type as a single-property object:
647692

@@ -664,7 +709,7 @@ Valid instances:
664709
{ "int32": 42 }
665710
```
666711

667-
#### Inline Unions
712+
### 5.9. Inline Unions
668713

669714
Inline unions extend a common abstract base type and use a selector property:
670715

@@ -715,10 +760,10 @@ Instance of this inline union:
715760
}
716761
```
717762

718-
## 5. Using Companion Specifications
763+
## 6. Using Companion Specifications
719764

720765
The JSON Structure Core specification is designed to be extensible through
721-
companion specifications that provide additional features and capabilities.
766+
companion specifications that provide additional features and capabilities.
722767

723768
The extended schema that includes all companion specifications is identified by
724769
the `https://json-structure.org/meta/extended/v0` URI. Each companion
@@ -727,6 +772,7 @@ specification is identified by a unique identifier that can be used in the
727772
document.
728773

729774
The feature identifiers for the companion specifications are:
775+
730776
- `JSONStructureAlternateNames`: Alternate names and descriptions for properties
731777
and types.
732778
- `JSONStructureUnits`: Symbols, scientific units, and currencies for numeric
@@ -736,7 +782,7 @@ The feature identifiers for the companion specifications are:
736782
- `JSONStructureConditionalComposition`: Conditional composition and validation
737783
rules.
738784

739-
### 5.1. Example: Using the `altnames` Keyword
785+
### 6.1. Example: Using the `altnames` Keyword
740786

741787
The [JSON Structure Alternate Names and Descriptions][JSTRUCT-ALTNAMES]
742788
companion specification introduces the `altnames` keyword to provide alternate
@@ -780,7 +826,7 @@ Here is an example of how to use the `altnames` keyword:
780826
```
781827

782828
Each named type or property in the schema has been given an `altnames` attribute
783-
that provides alternate names for the type or property.
829+
that provides alternate names for the type or property.
784830

785831
The `json` key is used to specify alternate names for JSON encoding, meaning
786832
that if the schema is used to encode or decode JSON data, the alternate key MUST
@@ -790,7 +836,7 @@ Keys beginning with `lang:` are reserved for providing localized alternate names
790836
that can be used for user interface display. Additional keys can be used for
791837
custom purposes, subject to no conflicts with reserved keys or prefixes.
792838

793-
### 5.2. Example: Using the `altenums` Keyword
839+
### 6.2. Example: Using the `altenums` Keyword
794840

795841
The [JSON Structure Alternate Enumerations][JSTRUCT-ALTNAMES] companion
796842
specification introduces the `altenums` keyword to provide alternative
@@ -833,7 +879,7 @@ possible values for the property. The `altenums` attribute provides alternative
833879
names for each enumeration value. The `lang:en` key provides English names for
834880
the enumeration values, and the `lang:de` key provides German names.
835881

836-
### 5.3. Example: Using the `unit` Keyword
882+
### 6.3. Example: Using the `unit` Keyword
837883

838884
The [JSON Structure Symbols, Scientific Units, and Currencies][JSTRUCT-UNITS]
839885
companion specification introduces the `unit` keyword to provide a standard way
@@ -859,7 +905,7 @@ In this example, the `value` property has a `unit` attribute that specifies the
859905
unit of measurement for the property. The unit of measurement is specified as a
860906
string value. In this case, the unit of measurement is "Pa" for Pascals.
861907

862-
### 5.4. Example: Using the `currency` Keyword
908+
### 6.4. Example: Using the `currency` Keyword
863909

864910
The [JSON Structure Symbols, Scientific Units, and Currencies][JSTRUCT-UNITS]
865911
companion specification also introduces the `currency` keyword to provide a
@@ -886,14 +932,14 @@ In this example, the `value` property has a `currency` attribute that specifies
886932
the currency for the property. The currency is specified as a string value. In
887933
this case, the currency is "USD" for US Dollars.
888934

889-
## 6. Using Validation
935+
## 7. Using Validation
890936

891937
The companion specifications for conditional composition and validation provide
892938
additional constructs for defining conditional validation rules and composing
893939
that resemble those found in prior versions of JSON Schema. However, those have
894940
been split out into optional extensions to keep the core schema language simple.
895941

896-
### 6.1. Example: Using Conditional Composition
942+
### 7.1. Example: Using Conditional Composition
897943

898944
The [JSON Structure Conditionals][JSTRUCT-COMPOSITION] companion specification
899945
introduces conditional composition constructs for combining multiple schema
@@ -904,7 +950,7 @@ as the `if`/`then`/`else` conditional construct.
904950
The specification has several examples that show how to use the conditional
905951
composition keywords.
906952

907-
### 6.2. Example: Using Validation Rules
953+
### 7.2. Example: Using Validation Rules
908954

909955
The [JSON Structure Validation][JSTRUCT-VALIDATION] companion specification
910956
introduces additional validation rules for JSON data.
@@ -917,4 +963,3 @@ introduces additional validation rules for JSON data.
917963
[JSTRUCT-UNITS]:https://github.com/json-structure/units
918964
[JSTRUCT-VALIDATION]: https://github.com/json-structure/validation
919965
[JSTRUCT-CORE]: https://github.com/json-structure/core
920-

0 commit comments

Comments
 (0)