-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdraft-newton-json-content-rules.xml
2200 lines (2188 loc) · 122 KB
/
draft-newton-json-content-rules.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc SYSTEM "http://xml2rfc.tools.ietf.org/authoring/rfc2629.dtd"
[
<!ENTITY RFC1166 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.1166.xml'>
<!ENTITY RFC2119 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml'>
<!ENTITY RFC3339 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.3339.xml'>
<!ENTITY RFC3629 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.3629.xml'>
<!ENTITY RFC3986 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml'>
<!ENTITY RFC4234 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.4234.xml'>
<!ENTITY RFC4627 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.4627.xml'>
<!ENTITY RFC4648 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml'>
<!ENTITY RFC5322 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.5322.xml'>
<!ENTITY RFC5952 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.5952.xml'>
<!ENTITY RFC7493 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.7493.xml'>
<!ENTITY RFC7942 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.7942.xml'>
<!ENTITY RFC8259 PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml'>
<!ENTITY I-D.cordell-jcr-co-constraints PUBLIC ''
'http://xml2rfc.tools.ietf.org/public/rfc/bibxml3/reference.I-D.cordell-jcr-co-constraints.xml'>
<!ENTITY ABNF PUBLIC ''
'jcr-abnf.txt'>
<!ENTITY first_example.json PUBLIC ''
'figs/first_example.json'>
<!ENTITY first_example.jcr PUBLIC ''
'figs/first_example.jcr'>
<!ENTITY first_example2.jcr PUBLIC ''
'figs/first_example2.jcr'>
<!ENTITY second_example.json PUBLIC ''
'figs/second_example.json'>
<!ENTITY second_example.jcr PUBLIC ''
'figs/second_example.jcr'>
<!ENTITY second_example2.jcr PUBLIC ''
'figs/second_example2.jcr'>
<!ENTITY second_example_override.jcr PUBLIC ''
'figs/second_example_override.jcr'>
<!ENTITY third_example1.jcr PUBLIC ''
'figs/third_example1.jcr'>
<!ENTITY third_example2.jcr PUBLIC ''
'figs/third_example2.jcr'>
<!ENTITY rfc4627_example.json PUBLIC ''
'figs/rfc4627_example.json'>
<!ENTITY rfc4627_example.jcr PUBLIC ''
'figs/rfc4627_example.jcr'>
<!ENTITY rfc4627_example2.jcr PUBLIC ''
'figs/rfc4627_example2.jcr'>
<!ENTITY rule_name_ruleset_id.jcr PUBLIC ''
'figs/rule_name_ruleset_id.jcr'>
<!ENTITY assignment_example.jcr PUBLIC ''
'figs/assignment_example.jcr'>
<!ENTITY assignment_example_2.jcr PUBLIC ''
'figs/assignment_example_2.jcr'>
<!ENTITY assignment_legacy_example.jcr PUBLIC ''
'figs/assignment_legacy_example.jcr'>
<!ENTITY annotation_example.jcr PUBLIC ''
'figs/annotation_example.jcr'>
<!ENTITY primitives_overview.jcr PUBLIC ''
'figs/primitives_overview.jcr'>
<!ENTITY root_annotations.jcr PUBLIC ''
'figs/root_annotations.jcr'>
<!ENTITY primitives_null.jcr PUBLIC ''
'figs/primitives_null.jcr'>
<!ENTITY primitives_boolean.jcr PUBLIC ''
'figs/primitives_boolean.jcr'>
<!ENTITY primitives_integer_and_float.jcr PUBLIC ''
'figs/primitives_integer_and_float.jcr'>
<!ENTITY primitives_float_range.jcr PUBLIC ''
'figs/primitives_float_range.jcr'>
<!ENTITY primitives_bit_integers.jcr PUBLIC ''
'figs/primitives_bit_integers.jcr'>
<!ENTITY illegal_integers.jcr PUBLIC ''
'figs/illegal_integers.jcr'>
<!ENTITY annotations-range-exclusive.jcr PUBLIC ''
'figs/annotations-range-exclusive.jcr'>
<!ENTITY primitives_strings.jcr PUBLIC ''
'figs/primitives_strings.jcr'>
<!ENTITY primitives_uris.jcr PUBLIC ''
'figs/primitives_uris.jcr'>
<!ENTITY primitives_misc.jcr PUBLIC ''
'figs/primitives_misc.jcr'>
<!ENTITY primitives_binary.jcr PUBLIC ''
'figs/primitives_binary.jcr'>
<!ENTITY type_choice.jcr PUBLIC ''
'figs/type_choice.jcr'>
<!ENTITY type_choice2.jcr PUBLIC ''
'figs/type_choice2.jcr'>
<!ENTITY member_specifications.jcr PUBLIC ''
'figs/member_specifications.jcr'>
<!ENTITY object_example.jcr PUBLIC ''
'figs/object_example.jcr'>
<!ENTITY object_example1.json PUBLIC ''
'figs/object_example1.json'>
<!ENTITY object_example2.json PUBLIC ''
'figs/object_example2.json'>
<!ENTITY object_order_eval.json PUBLIC ''
'figs/object_order_eval.json'>
<!ENTITY object_order_eval.jcr PUBLIC ''
'figs/object_order_eval.jcr'>
<!ENTITY array_example.jcr PUBLIC ''
'figs/array_example.jcr'>
<!ENTITY array_order_eval.jcr PUBLIC ''
'figs/array_order_eval.jcr'>
<!ENTITY array_order_eval.json PUBLIC ''
'figs/array_order_eval.json'>
<!ENTITY array_order_eval2.json PUBLIC ''
'figs/array_order_eval2.json'>
<!ENTITY array_unordered_eval.jcr PUBLIC ''
'figs/array_unordered_eval.jcr'>
<!ENTITY group_example.jcr PUBLIC ''
'figs/group_example.jcr'>
<!ENTITY group_example_for_validation.jcr PUBLIC ''
'figs/group_example_for_validation.jcr'>
<!ENTITY and_or_example.jcr PUBLIC ''
'figs/and_or_example.jcr'>
<!ENTITY mixed_and_or_bad.jcr PUBLIC ''
'figs/mixed_and_or_bad.jcr'>
<!ENTITY mixed_and_or_good.jcr PUBLIC ''
'figs/mixed_and_or_good.jcr'>
<!ENTITY repetition_min_max.jcr PUBLIC ''
'figs/repetition_min_max.jcr'>
<!ENTITY repetition_kleene.jcr PUBLIC ''
'figs/repetition_kleene.jcr'>
<!ENTITY repetition_step.jcr PUBLIC ''
'figs/repetition_step.jcr'>
<!ENTITY not_annotation.jcr PUBLIC ''
'figs/not_annotation.jcr'>
<!ENTITY single_line_directive_example.jcr PUBLIC ''
'figs/single_line_directive_example.jcr'>
<!ENTITY multi_line_directive_example.jcr PUBLIC ''
'figs/multi_line_directive_example.jcr'>
<!ENTITY jcr_version_current.jcr PUBLIC ''
'figs/jcr_version_current.jcr'>
<!ENTITY ruleset_id.jcr PUBLIC ''
'figs/ruleset_id.jcr'>
<!ENTITY any_member.jcr PUBLIC ''
'figs/any_member.jcr'>
<!ENTITY any_member1.json PUBLIC ''
'figs/any_member1.json'>
<!ENTITY any_member2.json PUBLIC ''
'figs/any_member2.json'>
<!ENTITY any_member_any_type.jcr PUBLIC ''
'figs/any_member_any_type.jcr'>
<!ENTITY any_member_any_type2.json PUBLIC ''
'figs/any_member_any_type2.json'>
<!ENTITY restrict_objects.jcr PUBLIC ''
'figs/restrict_objects.jcr'>
<!ENTITY restrict_objects1.json PUBLIC ''
'figs/restrict_objects1.json'>
<!ENTITY restrict_objects2.json PUBLIC ''
'figs/restrict_objects2.json'>
<!ENTITY unrestricted_arrays.jcr PUBLIC ''
'figs/unrestricted_arrays.jcr'>
<!ENTITY lists_of_values.jcr PUBLIC ''
'figs/lists_of_values.jcr'>
<!ENTITY groups_in_arrays.jcr PUBLIC ''
'figs/groups_in_arrays.jcr'>
<!ENTITY groups_in_arrays2.jcr PUBLIC ''
'figs/groups_in_arrays2.jcr'>
<!ENTITY groups_in_objects.jcr PUBLIC ''
'figs/groups_in_objects.jcr'>
<!ENTITY groups_in_objects_ignored.json PUBLIC ''
'figs/groups_in_objects_ignored.json'>
<!ENTITY groups_in_objects_ignored1.jcr PUBLIC ''
'figs/groups_in_objects_ignored1.jcr'>
<!ENTITY groups_in_objects_ignored2.jcr PUBLIC ''
'figs/groups_in_objects_ignored2.jcr'>
<!ENTITY groups_in_objects_ignored3.jcr PUBLIC ''
'figs/groups_in_objects_ignored3.jcr'>
<!ENTITY macro.jcr PUBLIC ''
'figs/macro.jcr'>
<!ENTITY object_mixin.jcr PUBLIC ''
'figs/object_mixin.jcr'>
<!ENTITY subordinate_dependents.jcr PUBLIC ''
'figs/subordinate_dependents.jcr'>
<!ENTITY subordinate_dependents_equiv.jcr PUBLIC ''
'figs/subordinate_dependents_equiv.jcr'>
<!ENTITY override1.jcr PUBLIC ''
'figs/override1.jcr'>
<!ENTITY override1.json PUBLIC ''
'figs/override1.json'>
<!ENTITY override2.jcr PUBLIC ''
'figs/override2.jcr'>
<!ENTITY override2.json PUBLIC ''
'figs/override2.json'>
<!ENTITY override3.jcr PUBLIC ''
'figs/override3.jcr'>
]>
<?rfc toc="yes"?>
<rfc category="std" docName="draft-newton-json-content-rules-10" ipr="trust200902">
<front>
<title abbrev="JSON Content Rules">A Language for Rules Describing JSON Content</title>
<author fullname="Andrew Lee Newton" initials="A.L." surname="Newton">
<organization abbrev="ARIN">American Registry for Internet Numbers</organization>
<address>
<postal>
<street>PO Box 232290</street>
<city>Centreville</city>
<region>VA</region>
<country>US</country>
<code>20120</code>
</postal>
<email>[email protected]</email>
<uri>http://www.arin.net</uri>
</address>
</author>
<author fullname="Pete Cordell" initials="P." surname="Cordell">
<organization>Codalogic</organization>
<address>
<postal>
<street>PO Box 30</street>
<city>Ipswich</city>
<country>UK</country>
<code>IP5 2WY</code>
</postal>
<email>[email protected]</email>
<uri>http://www.codalogic.com</uri>
</address>
</author>
<date/>
<abstract>
<t>
This document describes a language for specifying and testing the expected content of JSON structures
found in JSON-using protocols, software, and processes.
</t>
</abstract>
</front>
<middle>
<section title="Introduction">
<t>
This document describes JSON Content Rules (JCR), a language
for specifying and testing the interchange of data
in <xref target="RFC8259">JSON</xref> format used by computer protocols and processes.
The syntax of JCR is not JSON but is "JSON-like", possessing the conciseness and
utility that has made JSON popular.
</t>
<section title="Requirements Language">
<t>
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in <xref target="RFC2119">RFC 2119</xref>.
</t>
</section>
</section>
<section title="Motivation">
<t>
As a growing number of protocols use JSON, there is an increasing need to find better mechanisms
to help define such protocols.
</t>
<t>
In the past, protocols often used constrained grammar strings. Such strings could be defined by
example, but it was found better to use Backus-Naur Form (BNF), or variants such
as ABNF. The benefit of using ABNF over examples is that the full variation of what is allowed in a
protocol can be expressed in a single location. This leads to easier implementation and better
interoperability.
</t>
<t>
As protocols migrate to being defined in JSON, the same need to define the valid set of JSON
messages arises. It is conceivable to define the JSON-based message set by way of examples. But as
with constrained grammar strings, this can be cumbersome, incomplete and easily misinterpreted,
leading to the problems of implementation and interoperability mentioned earlier.
</t>
<t>
It would be theoretically possible to express the valid set of a protocol’s JSON messages using ABNF.
However, ABNF is difficult to get right at the best of times, and defining an ABNF that simultaneously
interwove the constraints of JSON and the constraints of the protocol into a single ABNF definition
would be a task few could, or would want to, achieve. Even if such were possible, much of what was
intended to describe the protocol, would be obscured by the aspects describing the JSON
constraints. Such an approach is likely to end up being only comprehendible by a machine, and be
impenetrable to humans. As such, arguably, such a definition would not satisfy it primary target
audience.
</t>
<t>
The solution is to move up a level of abstraction. In the same way JSON is a level of abstraction
above constrained grammar strings for representing protocols, a similar move up in abstraction level
is needed for the mechanism used to define such protocols.
</t>
<t>
JSON Content Rules (JCR) is such a step up in abstraction. It’s relation to JSON is that of ABNF to
constrained string grammars. By ‘knowing’ about JSON it can more accurately and concisely define
JSON messages than other methods that are less abstracted. In the same way that abstracted
languages such as Java and Python enable a programmer to work more efficiently than they can with
assembler, protocol developers can work more efficiently using JCR than they can with ABNF.
</t>
<t>
That said, JCR is not the only language in this space nor the only solution, beyond ABNF, to this
problem. Of the various method and languages that the authors know about, in addition to JCR,
there are format translators which algorithmically convert a specification from one format to
another (e.g. XML to JSON), abstraction languages such as Yang and CDDL, and at least one other JSON
specific language: JSON Schema.
</t>
<section title="Format Translation">
<t>
Format translation is an algorithmic approach to specifying protocol messages in multiple formats
by using one format as the base specification and an algorithm for translating that format
into another. One example would be the translation of XML into JSON using the BadgerFish
algorithm and software.
</t>
<t>
This approach often creates difficult protocol messages in the destination format (i.e. JSON in
the case of XML to JSON) which are hard to implement towards or debug. Additionally, while it be
fashionable to have multiple formats, most software implementations of protocols work best with
one format and often not well with others, if at all.
</t>
<t>
vCard and jCard are good examples of this. The original format and data model for vCard
are specified in MIME. jCard is an algorithmic conversion of vCard to jCard. Consequently,
writing software implementations of jCard requires software developers to have an intimate
knowledge of MIME, saving them little in the way of time or effort.
</t>
</section>
<section title="Abstraction Languages">
<t>
Abstraction languages are nothing new to the schema and data definition language space, with ASN.1
being a classic example of specifying a data model in a higher-level syntax and defined algorithms
for multiple data formats. ASN.1 supports many data formats, such as BER and DER and XER (XML Encoding Rules).
Yang is a more modern and popular abstraction language.
</t>
<t>
These languages have their place but suffer the same issues as format translators as they
require software implementors to spend valuable energy on a syntax that is not specific to the
software being implemented. Additionally, abstraction languages have, in many instances, specified
features in the data model that do not translate well to all data formats or may lack compelling
features because the language must cater to multiple formats.
</t>
<t>
With respect to JSON, CDDL is an abstraction language as it's data model is a superset of the
data model of JSON. In other words, it is possible to specify protocol messages in CDDL that are
not applicable to JSON. And because CDDL targets CBOR specifically, it does not benefit from being
JSON-like, as is the case of JCR, or specified in JSON, as is the case of JSON Schema.
</t>
</section>
<section title="JSON Schema vs JCR">
<t>
JSON Schema, like JCR, is a data definition language designed specifically for JSON. While JCR
is more tightly scoped to defining JSON protocol messages and content, JSON Schema is more
broadly scoped in its goals, including deeper aspects of data set linking and the semantic web.
</t>
<t>
JSON Schema benefits from being defined in JSON (as this makes implementations of JSON Schema tools
easier), but this benefit impacts readability of specifications defining content using it. To
demonstrate, the following examples define JSON using the classic example of a catalog object.
</t>
<figure anchor="example_catalog_json_schema">
<preamble>
In this example, the catalog entry is defined in JSON Schema.
</preamble>
<artwork xml:space="preserve" align="center">
{
"$schema": "http://json-schema.org/draft-06/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"exclusiveMinimum": 0
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": ["id", "name", "price"]
}
</artwork>
</figure>
<figure anchor="example_catalog_jcr">
<preamble>
For comparison, this example demonstrates the same catalog
entry as described in <xref target="example_catalog_json_schema"></xref>
but in JCR.
</preamble>
<artwork xml:space="preserve" align="center">
#jcr-version 0.9
; Product – A Product for Acme’s catalog
{
"id" : integer, ; Unique identifier for the product
"name" : string, ; Name of the product
"price" : @{min-exclusive} 0.0..,
"tags" : [ string + ] ?
}
</artwork>
</figure>
<t>
The above examples demonstrate that the JCR is more concise and conveys the same
information but in fewer lines in a syntax familiar with a JSON-aware software
implementor.
</t>
<t>
From a high-level view point, it could be said that JSON Schema is
like XML Schema whereas JCR is more like Compact RelaxNG.
</t>
<t>
Additionally, JCR syntax is a superset of JSON syntax, whereby specification authors may use example
JSON protocol messages as a starting point for defining JCR rules (as is described in
<xref target="a_first_example"></xref>). Consequently, the effort required to turn JSON examples into
JCR specifications is minimal compared to that required to create an equivalent JSON Schema.
This, combined with the brevity of describing rules
and the ability to name rules, allows specification authors to interleave their prose
with JCR rules in their specifications, facilitating describing semantics in close proximity
to syntax.
</t>
</section>
</section>
<section title="Uses">
<t>
JCR's primary focus is to help specification authors concisely and clearly describe
complex JSON data structures.
</t>
<t>
Being a precise, defined format reduces the potential for misunderstanding between what
specification authors intended and what software developers implement.
</t>
<t>
Being a machine-readable format, the examples in a specification can be validated by the
specified JCR, and it can be verified that the JCR represents the examples. This acts
like unit testing in software development, and has been done in the authoring of this document.
</t>
<t>
JCR aids software developers to verify that their implementations conform to specifications
by validating any generated JSON against the specified JCR. This can be used to highlight
bugs in their code, or possibly identify where a specification has omissions and requires
further work.
</t>
<t>
Specific examples of JCR and JSON can be included as part of conformance test vector sets to
give confidence that an implementation meets a specification. JCR's ability to be specific
in some locations, and loose in others, allows such tests to be run on a repeatable, automated
basis without requiring detailed human involvement to check the results.
</t>
<t>
JCR can help resolve interoperability issues by acting as an independent arbiter between
parties experiencing interoperability issues. Appealing to a JCR opinion offers the
potential for a quick and cheap resolution to a disagreement. (Naturally, either party
may disagree with the JCR result and take the matter further.)
</t>
<t>
Once software has been developed and deployed, JCR offers the potential for day-one in-the-field
monitoring of JSON message exchanges in order to highlight conformance issues that may have
slipped through the development phase.
</t>
<t>
Being a simple, defined language, JCR can also be used on an ad-hoc basis by developers as part
of the design process, such as during brainstorming and whiteboarding sessions, without risking
confusion over notation that may occur if an un-documented notation is used.
</t>
</section>
<section title="JCR Examples">
<t>
Being a superset of JSON syntax, those familiar with JSON will likely have an intuitive understanding
of many aspects of JCR. This section offers some JCR examples to give such readers a feel for JCR
before going into the detail.
</t>
<section title="A First Example: Specifying Content" anchor="a_first_example">
<t>
The following JSON data describes a JSON object with two members, "line-count" and
"word-count", each containing an integer.
</t>
<figure anchor="first_example.json">
<artwork xml:space="preserve" align="center">&first_example.json;</artwork>
</figure>
<t>
This is also JCR that describes a JSON object with a member named "line-count" that is
an integer that is exactly 3426 and a member named "word-count" that is an integer that
is exactly 27886.
</t>
<t>
For a protocol specification, it is probably more useful to specify that each member
is any integer and not specific, exact integers. Thus, a more practical JCR
description would be:
</t>
<figure anchor="first_example.jcr">
<artwork xml:space="preserve" align="center">&first_example.jcr;</artwork>
</figure>
<t>
Since line counts and word counts should be either zero or a positive integer,
the specification may be further narrowed:
</t>
<figure anchor="first_example2.jcr">
<artwork xml:space="preserve" align="center">&first_example2.jcr;</artwork>
</figure>
</section>
<section title="A Second Example: Testing Content">
<t>
Building on the first example, this second example describes the same object
but with the addition of another member, "file-name". An example JSON instance is:
</t>
<figure anchor="second_example.json">
<artwork xml:space="preserve" align="center">&second_example.json;</artwork>
</figure>
<t>
The following JCR describes such objects:
</t>
<figure anchor="second_example.jcr">
<artwork xml:space="preserve" align="center">&second_example.jcr;</artwork>
</figure>
<t>
For the purposes of writing a protocol specification, JCR may be broken down into
named rules to reduce complexity and to enable re-use. The following example takes
the JCR from above and rewrites the members as named rules:
</t>
<figure anchor="second_example2.jcr">
<artwork xml:space="preserve" align="center">&second_example2.jcr;</artwork>
</figure>
<t>
With each member specified as a named rule, software testers can override them locally
for specific test cases. In the following example, the named rules are locally overridden
for the test case where the file name is "rfc4627.txt":
</t>
<figure anchor="second_example_override.jcr">
<artwork xml:space="preserve" align="center">&second_example_override.jcr;</artwork>
</figure>
<t>
This example shows how a protocol specification can describe a JSON object in general and
a test environment can override the rules for testing specific cases.
</t>
<t>
All figures used in this specification are available <eref target="https://github.com/arineng/jcr/tree/master/figs">here</eref>.
</t>
</section>
<section title="A Third Example: Combining Rulesets">
<t>
In addition to defining rules, which relate to individual JSON values,
JCR also has directives, which have a more ruleset-wide effect.
</t>
<t>
Currently defined directives include jcr-version, ruleset-id and import.
jcr-version specifies the version of JCR used by a ruleset, and allows
future versions of JCR. ruleset-id and import support combining rules
from multiple rulesets.
</t>
<t>
Extending the previous example, it might be decided that the unsigned integer type associated
with the $lc and $wc is so useful that it should be extracted into a ruleset of
common utility types so that it can be used in other rulesets. Such a ruleset may
look like:
</t>
<figure anchor="thrid_example2.jcr">
<artwork xml:space="preserve" align="center">&third_example2.jcr;</artwork>
</figure>
<t>
As this may be a long-lived ruleset, the jcr-version directive make it clear
that JCR version 1.0 is being used. The ruleset is given the
identity 'com.example.common-types' using the ruleset-id directive. The rule
for the type is assigned the rule name 'count'.
</t>
<t>
A ruleset that makes use of the count type, may look as follows:
</t>
<figure anchor="thrid_example1.jcr">
<artwork xml:space="preserve" align="center">&third_example1.jcr;</artwork>
</figure>
<t>
To make use of the count type, it is first necessary to import the
'com.example.common-types' ruleset, using the import directive. As part of the
import, the 'com.example.common-types' ruleset is given an alias, 'ct', with which
to refer to it. It is then possible to use the imported count type as '$ct.count'.
</t>
</section>
</section>
<section title="Overview of the Language">
<t>
JCR is composed of rules (as the name suggests). A collection of rules that is processed
together is a ruleset. Rulesets may also contain comments, blank lines, and directives
that apply to the processing of a ruleset.
</t>
<t>
Rules are composed of two parts, an optional rule name and
a rule specification. A rule specification can be either a type
specification or a member specification. A member specification
consists of a member name specification and a type specification.
</t>
<t>
A type specification is used to specify constraints on a superset
of JSON values (e.g. number / string / object / array etc.). In
addition to defining primitive types (such as string and integer),
array and object types, type specifications may define the
JCR specific concept of group types.
</t>
<t>
Type specifications corresponding to arrays, objects and groups may
be composed of other rule specifications.
</t>
<t>
A member specification is used to specify constraints on members of a JSON object.
</t>
<t>
Rules that have a rule name may be referenced in place of
rule specifications.
</t>
<t>
Rules may be defined across line boundaries and there is no line
continuation syntax.
</t>
<t>
Any rule without a rule name is considered a root rule. Such a rule
MUST be a type specification. Unless otherwise
specified, all the root rules of a ruleset are evaluated against a JSON instance or document.
</t>
<t>
Rule specifications may be augmented with annotations to specify
additional constraints and properties. For example, arrays can be
augmented with an 'unordered' annotation to indicate that the order
of its members isn't significant.
</t>
<t>
The syntax for each form of type specification varies depending on the type.
For example:
</t>
<figure anchor="primitive_overview.jcr">
<artwork xml:space="preserve" align="center">&primitives_overview.jcr;</artwork>
</figure>
<t>
Putting it all together, the JSON in <xref target="rfc4627-example-1"></xref>
is described by the JCR in <xref target="rfc4627-example-1-compact-rules"></xref>.
</t>
<figure anchor="rfc4627-example-1" title="Example JSON shamelessly lifted from RFC 8259">
<artwork xml:space="preserve" align="center">&rfc4627_example.json;</artwork>
</figure>
<figure anchor="rfc4627-example-1-compact-rules" title="JCR for JSON example from RFC 8259">
<artwork xml:space="preserve" align="center">&rfc4627_example2.jcr;</artwork>
</figure>
<t>
In addition to defining rules, JCR also has directives. These have a more ruleset-wide
effect. Simple uses of JCR will likely not use directives.
</t>
</section>
<section title="Language Components">
<t>
This section describes each component of the JCR language in detail.
</t>
<section title="Character Encoding">
<t>
Like JSON, JCR rulesets MUST be encoded using UTF-8 <xref target="RFC3629">RFC 3629</xref>
unless used entirely within a private, closed ecosystem.
</t>
<t>
This document assumes that both JCR rulesets, and JSON instances being validated
are encoded using UTF-8.
Issues related to handling JCR rulesets or JSON instances that are not encoded using
UTF-8 are outside the scope of this document.
</t>
</section>
<section title="Comments">
<t>
Comments are the same as comments in <xref target="RFC4234">ABNF</xref>. They start with a semi-colon (';') and
continue to the end of the line.
</t>
<t>
Blank lines are allowed. These can be used, for example, to further aid readability.
</t>
</section>
<section title="Names and Identifiers" anchor="names-and-identifiers">
<t>
JCR uses names and identifiers to enable cross-referencing one part of a ruleset with
another, or from one ruleset to another. There are different types of names and different
type of identifiers. For example, a local rule name is a name, and a ruleset-id is an
identifier.
</t>
<t>
A name must start with an ASCII alphabetic character (a-z,A-Z) and must contain only ASCII
alphabetic characters, numeric characters, the hyphen character ('-') and the underscore
character ('_'). Names are case sensitive.
</t>
<t>
An identifier must start with an ASCII alphabetic character (a-z,A-Z) and can be followed
by any character other than whitespace and the closing brace ('}'). Identifiers are treated
as opaque strings, and therefore case-sensitive.
</t>
</section>
<section title="Directives">
<t>
Directives modify the processing of a ruleset. If present, they typically appear at the start of a
ruleset, before any rules are defined, but they can be placed in other parts of the ruleset if necessary.
Simpler rulesets need not include any directives.
</t>
<t>
There are two forms of the directive, the
single line directive and the multi-line directive.
</t>
<t>
Single line directives appear on their own line in a ruleset, begin
with a hash character ('#') and are terminated by the end of the line.
They take the following form:
</t>
<figure anchor="single_line_directive_example.jcr">
<artwork xml:space="preserve" align="center">&single_line_directive_example.jcr;</artwork>
</figure>
<t>
Multi-line directives also appear on their own lines, but may span multiple lines.
They begin with the character sequence "#{" and end with "}". The take the
following form:
</t>
<figure anchor="multi_line_directive_example.jcr">
<artwork xml:space="preserve" align="center">&multi_line_directive_example.jcr;</artwork>
</figure>
<t>
This specification defines the directives "jcr-version", "ruleset-id",
and "import", but other directives may be defined in future.
</t>
<section title="jcr-version">
<!-- We'll obviously have to revisit this section upon publication.-->
<t>
This directive declares that the ruleset complies with a specific version of this
standard. The version is expressed as a major integer followed by a period followed
by a minor integer.
</t>
<figure anchor="jcr_version_current.jcr">
<artwork xml:space="preserve" align="center">&jcr_version_current.jcr;</artwork>
</figure>
<t>
The major.minor number signifying compliance with this document is "0.9". Upon publication
of this specification as an IETF proposed standard, it will be "1.0".
<cref>
NOTE: This will be removed in the final version.
</cref>
</t>
<!-- This will be put into a file when the jcr validator actually accepts 1.0. Right now it accepts
the working version number. -->
<figure anchor="jcr_version_final.jcr">
<artwork xml:space="preserve" align="center">
# jcr-version 1.0
</artwork>
</figure>
<t>
This directive may have optional extension identifiers following the version number.
Each extension identifiers is preceded by the plus ('+') character and separated by white space.
An extension identifier has the form of an identifier as described in <xref target="names-and-identifiers"></xref>.
The structure of extension identifiers is specific to the extension,
but it is recommended that they are terminated by a version number.
</t>
<!-- This will be put into a file when the jcr validator actually accepts 1.0. Right now it accepts
the working version number. -->
<figure anchor="jcr_version_extensions.jcr">
<artwork xml:space="preserve" align="center">
# jcr-version 1.0 +co-constraints-1.2 +jcr-doc-1.0
</artwork>
</figure>
<t>
A maximum of one jcr-version directive is permitted in a ruleset.
Ruleset authors are advised to place this directive as the first line of a ruleset.
</t>
</section>
<section title="ruleset-id" anchor="ruleset-id">
<t>
This directive identifies a ruleset to rule processors. It takes the form:
</t>
<figure anchor="ruleset_id.jcr">
<artwork xml:space="preserve" align="center">&ruleset_id.jcr;</artwork>
</figure>
<t>
The ruleset identifier has the form of an identifier as described in <xref target="names-and-identifiers"></xref>.
The identifier can be a URL (e.g. http://example.com/foo), an inverted domain name
(e.g. com.example.foo) or have any other internal structure that
a ruleset author deems appropriate. To a JCR processor the identifier is treated as
an opaque, case-sensitive string. An identifier that is URI based should not be
taken to imply that the ruleset is accessible over the Internet at that address
(although it is not prevented from being accessible in such a way).
</t>
<t>
A maximum of one ruleset-id directive is permitted in a ruleset.
If present, it is suggested that it be the second line of a ruleset, following the
jcr-version directive, or the first line if no jcr-version directive is present.
</t>
</section>
<section title="import" anchor="import">
<t>
The import directive specifies that another ruleset is to have its rules
evaluated in addition to the ruleset where the directive appears.
</t>
<t>
The following is an example:
</t>
<!-- We don't have control of example.com, so this can't be put in as a test.-->
<figure anchor="import_directive.jcr">
<artwork xml:space="preserve" align="center">
# import http://example.com/rfc9999 as rfc9999
# import http://example.com/rfc9997
</artwork>
</figure>
<t>
The identifier after the import keyword is a ruleset identifier.
As such, it is an identifier as described in <xref target="names-and-identifiers"/>.
The ruleset that is imported is identified by having the specified ruleset identifier
assigned in its #ruleset-id directive (See <xref target="ruleset-id"/>).
How a JCR processor locates the imported ruleset is out of scope for this document.
</t>
<t>
The string after the as keyword acts as an alias for the identifier. An alias has
the form of a name as described in <xref target="names-and-identifiers"/>.
Including the as keyword followed by an alias is optional.
</t>
<t>
The rule names of the ruleset being imported may be referenced by prepending
the alias followed by a period character ('.') followed by the local rule name
(i.e. "alias.name"). To continue the example above, if the ruleset identified as http://example.com/rfc9999
were to have a rule named 'encoding', rules in the ruleset importing it can
refer to that rule as 'rfc9999.encoding'.
</t>
<t>
If an import directive does not specify an alias with the 'as' keyword, the local
names of the imported ruleset effectively become local to the importing ruleset,
except that a referenced name without an alias is sought in the importing ruleset
before being sought in each of the unaliased imported rulesets.
</t>
</section>
</section>
<section title="Rules">
<t>
Rules have two main components, an optional rule name assignment and a rule specification.
</t>
<t>
Rules have no statement terminator and therefore no need for a line continuation syntax.
Rules may be defined across line boundaries.
</t>
<t>
A rule specification can be a type specification or a member specification.
</t>
<t>
Type specifications define arrays, objects, etc... of JSON or may reference other rules
using rule names. Most type specifications can be defined with repetitions for specifying
the frequency of the type being defined. In addition to the type specifications describing
JSON types, there is an additional group specification for grouping specifications.
</t>
<t>
Member specifications define members of JSON objects, and are composed of a member name specification
and either a type specification or a rule name referencing a type specification.
</t>
<t>
Rules may also contain annotations which may affect the evaluation of all or part of a rule.
Rules without a rule name assignment are considered root rules, though rules with a rule
name assignment can be considered a root rule with the appropriate annotation.
</t>
<t>
Type specifications, depending on their type, can contain zero or more other
specifications or rule names. For example, an object specification might contain multiple
member specifications or rule names that resolve to member specifications or a mixture
of member specifications and rule names.
</t>
<t>
For the purposes of this document, specifications
and rule names composing other specifications are called subordinate components.
</t>
</section>
<section title="Rule Names and Assignments">
<t>
Rule names are used to represent rule specifications so they can be referenced elsewhere
in a ruleset. A rule name can be used in two contexts; rule specification assignment,
and rule specification referencing.
</t>
<t>
Rule names are signified with the dollar character ('$'), which is
not part of the rule name itself. Rule names have two components, an
optional ruleset identifier alias and a local rule name. If a ruleset identifier alias
is present, it is separated from the local rule name by a dot character ('.'). Both ruleset
identifier aliases and local rule names are types of name (see <xref target="names-and-identifiers"></xref>).
</t>
<t>
When a rule name is used in the rule specification assignment context, only the local rule name part can be
present. In this context, the local rule name must be unique within a ruleset
(that is, no two rule name assignments may use the same local rule
name in the same ruleset).
</t>
<t>
In rule name assignments, the rule name is separated from the rule specification using the '='
character.
</t>
<figure anchor="assignment_example.jcr">
<artwork xml:space="preserve" align="center">&assignment_example.jcr;</artwork>
</figure>
<t>
In the rule specification referencing context, a rule name, prefixed by the dollar character ('$'), is
used in place of a rule specification.
</t>
<figure anchor="assignment_example_2.jcr">
<artwork xml:space="preserve" align="center">&assignment_example_2.jcr;</artwork>
</figure>
<t>
Ruleset identifier aliases may be included in a rule name that is used as a reference.
They enable referencing rules from another ruleset. Simple use cases of JCR will
most likely not use ruleset identifiers.
</t>
<figure anchor="rule_name_ruleset_id.jcr">
<preamble>
In Figure <xref target="rule_name_ruleset_id.jcr"/> below,
"http://ietf.org/rfcYYYY.JCR" and "http://ietf.org/rfcXXXX.JCR" are ruleset
identifiers and "rfcXXXX" is a ruleset identifier alias. See Section
<xref target="import"/> for details on defining and using ruleset identifier aliases.
</preamble>
<artwork align="center" xml:space="preserve">&rule_name_ruleset_id.jcr;</artwork>
</figure>
<t>
The order of rule name references in a ruleset relative to their referenced rule name
assignment is not significant. Rule name references can be either before or after
their referenced rule name assignment.
</t>
</section>
<section title="Annotations">
<t>
Annotations may appear before a rule name assignment, before a type or member specification, or
before a rule name contained within a type specification. In each place, there may be
zero or more annotations.
Each annotation begins with the
character sequence "@{" and ends with "}". The following is an example of a type specification
with the not annotation:
</t>
<figure anchor="annotation_example.jcr">
<artwork xml:space="preserve" align="center">&annotation_example.jcr;</artwork>
</figure>
<t>
The @{not} annotation is described in <xref target="not_annotation"></xref>.
</t>
<t>
The @{root} annotation is described in <xref target="starting-points"></xref>.
</t>
<t>
The @{unordered} annotation is described in <xref target="unordered_array_specifications"></xref>.
</t>
<t>
The @{min-exclusive} and @{max-exclusive} annotations are described in <xref target="numbers"></xref>.
</t>
<t>
Other annotations may be defined for other purposes in future.
</t>
<section title="@{not} - Negating Evaluation" anchor="not_annotation">
<t>
The evaluation of a rule can be changed with the @{not} annotation. With this annotation,
a rule that would otherwise match does not, and a rule that would not have matched does.
</t>
<figure anchor="not_annotation.jcr">
<artwork xml:space="preserve" align="center">¬_annotation.jcr;</artwork>
</figure>
</section>
</section>
<section title="Repetition" anchor="repetition">
<t>
Evaluation of subordinate components in array, object, and group specifications may be succeeded by
a repetition expression denoting how many times the subordinate component may appear in a JSON instance.
</t>
<t>
Repetition expressions are specified using a Kleene symbol ('?', '+', or '*') or with
the '*' symbol succeeded by specific minimum and/or maximum values, each being non-negative integers. Repetition expressions
may also be appended with a step expression, which consists of the '%' symbol followed by a positive integer.
</t>
<t>
When no repetition expression is present, both the minimum and maximum
are 1.
</t>
<t>
A minimum and maximum can be expressed by giving the minimum followed by two period characters
('..') followed by the maximum, with either the minimum or maximum being optional. When the
minimum is not explicitly specified, it is assumed to be zero. When the maximum is not explicitly
specified, it is assumed to be positive infinity.
</t>
<figure anchor="repetition_min_max.jcr">
<artwork xml:space="preserve" align="center">&repetition_min_max.jcr;</artwork>
</figure>
<t>
The allowable Kleene operators are the question mark character ('?') which
specifies zero or one (i.e. optional), the plus character ('+') which specifies
one or more, and the asterisk character ('*') which specifies zero or more.
</t>
<figure anchor="repetition_kleene.jcr">
<artwork xml:space="preserve" align="center">&repetition_kleene.jcr;</artwork>
</figure>
<t>
A repetition step expression may follow a minimum to maximum expression or the
zero or more Kleene operator or the one or more Kleene operator.
<list style="symbols">
<t>
When the repetition step
follows a minimum to maximum expression or the zero or more Kleene operator ('*'), it
specifies that the total number of repetitions present in the JSON instance
being validated minus the minimum repetition value
must be a multiple of the repetition step