Skip to content

Commit 25e4ab0

Browse files
committed
Revise the readOnly keyword
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 34decf1 commit 25e4ab0

File tree

1 file changed

+67
-47
lines changed

1 file changed

+67
-47
lines changed

content/2020-12/meta-data/readOnly.markdown

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,82 +28,102 @@ related:
2828
keyword: deprecated
2929
---
3030

31-
The `readOnly` keyword is used to indicate that the value of a particular property is managed exclusively by the owning authority, and attempts by an application to modify the value of this property are expected to be ignored or rejected by that authority. It essentially means that the instance value should not be modified.
31+
The `readOnly` keyword, when set to `true`, signifies that an instance value
32+
(such as a specific object property) cannot be modified or removed, whatever
33+
that means in the context of the system. For example, form generators may rely
34+
on this keyword to mark the corresponding input as read only. This keyword does
35+
not affect validation, but the evaluator will collect its value as an
36+
annotation.
3237

33-
It's important to note that this keyword doesn't imply the schema itself is writable; schemas must be treated as immutable. Instead, the keyword specifies instances where read/write operation semantics are use case specific.
38+
{{<best-practice>}}
3439

35-
* `readOnly` does not affect data validation but serves as an informative annotation.
40+
Avoid setting this keyword to the default value `false`. If an instance value
41+
is not considered to be read only, the best practice is to omit the use of this
42+
keyword altogether. This prevents unnecessarily generating and collecting an
43+
annotation that does not carry any additional meaning.
3644

37-
## Examples
45+
Also avoid simultaneously setting this keyword and the [`writeOnly`]({{< ref
46+
"2020-12/meta-data/writeonly" >}}) keyword to `true` for the same instance
47+
location, resulting in ambiguous semantics.
3848

39-
{{<schema `Schema with 'readOnly' keyword`>}}
40-
{
41-
"$schema": "https://json-schema.org/draft/2020-12/schema",
42-
"readOnly": true,
43-
"type": "number"
44-
}
45-
{{</schema>}}
49+
{{</best-practice>}}
4650

47-
{{<instance-pass `An instance with a numeric value is valid`>}}
48-
45
49-
{{</instance-pass>}}
51+
{{<common-pitfall>}}
5052

51-
{{<instance-annotation>}}
52-
{ "keyword": "/readOnly", "instance": "", "value": true }
53-
{{</instance-annotation>}}
53+
Tooling makers must be careful when statically traversing schemas in search of
54+
occurences of this keyword. It is possible for schemas to make use of this
55+
keyword behind conditional operators, references, or any other type of keyword
56+
that makes it hard or even impossible to correctly locate these values without
57+
fully evaluating the schema against an instance. The only bullet proof method
58+
is through annotation collection.
59+
60+
For example, an instance property might only be read only under certain
61+
conditions determined by a dynamic operator like [`anyOf`]({{< ref
62+
"2020-12/applicator/anyof" >}}).
63+
64+
{{</common-pitfall>}}
65+
66+
{{<metaschema-check-type `boolean`>}}
67+
68+
## Examples
5469

55-
{{<schema `Schema with logical operators`>}}
70+
{{<schema `A schema that statically marks the id optional object property as read only`>}}
5671
{
5772
"$schema": "https://json-schema.org/draft/2020-12/schema",
58-
"if": {
59-
"properties": {
60-
"immutable": { "const": true }
61-
}
62-
},
63-
"then": {
64-
"readOnly": true
65-
},
66-
"else": {
67-
"readOnly": false
73+
"properties": {
74+
"id": { "readOnly": true },
75+
"value": { "type": "integer" }
6876
}
6977
}
7078
{{</schema>}}
7179

72-
{{<instance-pass>}}
73-
{ "immutable": false }
80+
{{<instance-pass `An object value that defines the read only property is valid but an annotation is emitted`>}}
81+
{ "id": 1234, "value": 5 }
7482
{{</instance-pass>}}
7583

7684
{{<instance-annotation>}}
77-
{ "keyword": "/else/readOnly", "instance": "", "value": false }
85+
{ "keyword": "/properties/id/readOnly", "instance": "/id", "value": true }
7886
{{</instance-annotation>}}
7987

80-
{{<instance-pass>}}
81-
{ "immutable": true }
88+
{{<instance-pass `An object value that does not define the read only property is valid and no annotation is emitted`>}}
89+
{ "value": 5 }
8290
{{</instance-pass>}}
8391

84-
{{<instance-annotation>}}
85-
{ "keyword": "/then/readOnly", "instance": "", "value": true }
86-
{{</instance-annotation>}}
92+
{{<instance-fail `An object value that does not match the schema is invalid and no annotations are emitted`>}}
93+
{ "id": 1234, "value": null }
94+
{{</instance-fail>}}
8795

88-
{{<schema `Schema with multiple annotations for the same instance`>}}
96+
{{<schema `A schema that dynamically marks the id optional object property as read only based on the presence of the data property`>}}
8997
{
9098
"$schema": "https://json-schema.org/draft/2020-12/schema",
91-
"readOnly": true,
92-
"$ref": "#/$defs/name",
93-
"$defs": {
94-
"name": {
95-
"readOnly": true,
96-
"type": "string"
99+
"properties": {
100+
"id": true,
101+
"value": { "type": "integer" }
102+
},
103+
"dependentSchemas": {
104+
"value": {
105+
"properties": { "id": { "readOnly": true } }
97106
}
98107
}
99108
}
100109
{{</schema>}}
101110

102-
{{<instance-pass>}}
103-
"John Doe"
111+
{{<instance-pass `An object value that defines both properties is valid but an annotation is emitted`>}}
112+
{ "id": 1234, "value": 5 }
104113
{{</instance-pass>}}
105114

106115
{{<instance-annotation>}}
107-
{ "keyword": "/readOnly", "instance": "", "value": true }
108-
{ "keyword": "/$ref/readOnly", "instance": "", "value": true }
116+
{ "keyword": "/dependentSchemas/value/properties/id/readOnly", "instance": "/id", "value": true }
109117
{{</instance-annotation>}}
118+
119+
{{<instance-pass `An object value that only defines the value property is valid and no annotation is emitted`>}}
120+
{ "value": 5 }
121+
{{</instance-pass>}}
122+
123+
{{<instance-pass `An object value that only defines the id property is valid and no annotation is emitted`>}}
124+
{ "id": 1234 }
125+
{{</instance-pass>}}
126+
127+
{{<instance-fail `An object value that does not match the schema is invalid and no annotations are emitted`>}}
128+
{ "value": null }
129+
{{</instance-fail>}}

0 commit comments

Comments
 (0)