Skip to content

Commit 204d3a4

Browse files
committed
Use if-then-else for better-steered parsing
anyOf and oneOf now only used for trivial distinctions, this makes schemas much more robust since errors can be caught early and error messages become actually useful.
1 parent 86d7703 commit 204d3a4

File tree

6 files changed

+148
-101
lines changed

6 files changed

+148
-101
lines changed

share/openPMD/json_schema/attribute_defs.toml

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,15 @@
55
# Vectors of strings #
66
######################
77

8-
[["$defs".vec_string_attribute.oneOf]]
9-
title = "Shorthand notation"
10-
anyOf = [
11-
{ type = "string" },
12-
{ type = "array", items = { "type" = "string" } },
13-
]
8+
["$defs".vec_string_attribute.if]
9+
type = "object"
1410

15-
[["$defs".vec_string_attribute.oneOf]]
11+
["$defs".vec_string_attribute.then]
1612
title = "Long notation"
1713
type = "object"
1814
required = ["value", "datatype"]
1915

20-
["$defs".vec_string_attribute.oneOf.properties]
16+
["$defs".vec_string_attribute.then.properties]
2117

2218
value.anyOf = [
2319
{ type = "string" },
@@ -35,23 +31,24 @@ datatype.enum = [
3531
"VEC_UCHAR",
3632
]
3733

34+
["$defs".vec_string_attribute.else]
35+
title = "Shorthand notation"
36+
anyOf = [{ type = "string" }, { type = "array", items = { "type" = "string" } }]
37+
38+
3839
##################
3940
# Vectors of int #
4041
##################
4142

42-
[["$defs".vec_int_attribute.oneOf]]
43-
title = "Shorthand notation"
44-
anyOf = [
45-
{ type = "integer" },
46-
{ type = "array", items = { "type" = "integer" } },
47-
]
43+
["$defs".vec_int_attribute.if]
44+
type = "object"
4845

49-
[["$defs".vec_int_attribute.oneOf]]
46+
["$defs".vec_int_attribute.then]
5047
title = "Long notation"
5148
type = "object"
5249
required = ["value", "datatype"]
5350

54-
["$defs".vec_int_attribute.oneOf.properties]
51+
["$defs".vec_int_attribute.then.properties]
5552

5653
value.anyOf = [
5754
{ type = "integer" },
@@ -77,23 +74,26 @@ datatype.enum = [
7774
"VEC_ULONGLONG",
7875
]
7976

77+
["$defs".vec_int_attribute.else]
78+
title = "Shorthand notation"
79+
anyOf = [
80+
{ type = "integer" },
81+
{ type = "array", items = { "type" = "integer" } },
82+
]
83+
8084
####################
8185
# Vectors of float #
8286
####################
8387

84-
[["$defs".vec_float_attribute.oneOf]]
85-
title = "Shorthand notation"
86-
anyOf = [
87-
{ type = "number" },
88-
{ type = "array", items = { "type" = "number" } },
89-
]
88+
["$defs".vec_float_attribute.if]
89+
type = "object"
9090

91-
[["$defs".vec_float_attribute.oneOf]]
91+
["$defs".vec_float_attribute.then]
9292
title = "Long notation"
9393
type = "object"
9494
required = ["value", "datatype"]
9595

96-
["$defs".vec_float_attribute.oneOf.properties]
96+
["$defs".vec_float_attribute.then.properties]
9797

9898
value.anyOf = [
9999
{ type = "number" },
@@ -134,58 +134,67 @@ datatype.enum = [
134134
"VEC_CLONG_DOUBLE",
135135
]
136136

137+
["$defs".vec_float_attribute.else]
138+
title = "Shorthand notation"
139+
anyOf = [{ type = "number" }, { type = "array", items = { "type" = "number" } }]
140+
137141
###########################
138142
# Special case: #
139143
# unitDimension attribute #
140144
###########################
141145

142-
[["$defs".unitDimension.oneOf]]
143-
title = "Shorthand notation"
144-
type = "array"
145-
items.type = "number"
146+
["$defs".unitDimension.if]
147+
type = "object"
146148

147-
[["$defs".unitDimension.oneOf]]
149+
["$defs".unitDimension.then]
148150
title = "Long notation"
149151
type = "object"
150152
required = ["value", "datatype"]
151153

152-
["$defs".unitDimension.oneOf.properties]
154+
["$defs".unitDimension.then.properties]
153155

154156
value = { type = "array", items = { type = "number" } }
155157
datatype.const = "ARR_DBL_7"
156158

159+
["$defs".unitDimension.else]
160+
title = "Shorthand notation"
161+
type = "array"
162+
items.type = "number"
163+
157164
#####################
158165
# string attributes #
159166
#####################
160167

161-
[["$defs".string_attribute.oneOf]]
162-
title = "Shorthand notation"
163-
type = "string"
168+
["$defs".string_attribute.if]
169+
type = "object"
164170

165-
[["$defs".string_attribute.oneOf]]
171+
["$defs".string_attribute.then]
166172
title = "Long notation"
167173
type = "object"
168174
required = ["value", "datatype"]
169175

170-
["$defs".string_attribute.oneOf.properties]
176+
["$defs".string_attribute.then.properties]
171177

172178
value.type = "string"
173179
datatype.enum = ["STRING", "CHAR", "SCHAR", "UCHAR"]
174180

181+
["$defs".string_attribute.else]
182+
title = "Shorthand notation"
183+
type = "string"
184+
175185
##################
176186
# int attributes #
177187
##################
178188

179-
[["$defs".int_attribute.oneOf]]
180-
title = "Shorthand notation"
181-
type = "integer"
189+
["$defs".int_attribute.if]
190+
type = "object"
182191

183-
[["$defs".int_attribute.oneOf]]
192+
["$defs".int_attribute.then]
184193
title = "Long notation"
185194
type = "object"
186195
required = ["value", "datatype"]
187196

188-
["$defs".int_attribute.oneOf.properties]
197+
["$defs".int_attribute.then.properties]
189198

190199
value.type = "integer"
191200
datatype.enum = [
@@ -199,20 +208,23 @@ datatype.enum = [
199208
"ULONGLONG",
200209
]
201210

211+
["$defs".int_attribute.else]
212+
title = "Shorthand notation"
213+
type = "integer"
214+
202215
####################
203216
# float attributes #
204217
####################
205218

206-
[["$defs".float_attribute.oneOf]]
207-
title = "Shorthand notation"
208-
type = "number"
219+
["$defs".float_attribute.if]
220+
type = "object"
209221

210-
[["$defs".float_attribute.oneOf]]
222+
["$defs".float_attribute.then]
211223
title = "Long notation"
212224
type = "object"
213225
required = ["value", "datatype"]
214226

215-
["$defs".float_attribute.oneOf.properties]
227+
["$defs".float_attribute.then.properties]
216228

217229
value.type = "number"
218230
datatype.enum = [
@@ -234,3 +246,8 @@ datatype.enum = [
234246
"CDOUBLE",
235247
"CLONG_DOUBLE",
236248
]
249+
250+
251+
["$defs".float_attribute.else]
252+
title = "Shorthand notation"
253+
type = "number"

share/openPMD/json_schema/attributes.toml

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,16 @@ type = "object"
99
title = "Dictionary of attributes"
1010
description = "Generic layout of an attributes object."
1111

12-
[[oneOf.patternProperties.".*".oneOf]]
13-
title = "A generic attribute - short form"
14-
anyOf = [
15-
# Any primitive value
16-
{ not = { anyOf = [
17-
{ type = "object", title = "An object" },
18-
{ type = "array", title = "An array" },
19-
] }, title = "No complex type" },
20-
# Or an array of any primitive value
21-
{ type = "array", items = { not = { anyOf = [
22-
{ type = "object", title = "An object" },
23-
{ type = "array", title = "An array" },
24-
] } }, title = "An array of non-complex types" },
25-
]
12+
[oneOf.patternProperties.".*".if]
13+
type = "object"
2614

27-
[[oneOf.patternProperties.".*".oneOf]]
15+
[oneOf.patternProperties.".*".then]
2816
title = "A generic attribute - long form"
2917
type = "object"
18+
required = ["value", "datatype"]
19+
maxProperties = 2
3020

31-
[oneOf.patternProperties.".*".oneOf.properties]
32-
33-
value.anyOf = [
21+
properties.value.anyOf = [
3422
# Any primitive value
3523
{ not = { anyOf = [
3624
{ type = "object", title = "An object" },
@@ -43,8 +31,8 @@ value.anyOf = [
4331
] } }, title = "An array of non-complex types" },
4432
]
4533

46-
datatype.type = "string"
47-
datatype.enum = [
34+
properties.datatype.type = "string"
35+
properties.datatype.enum = [
4836
"CHAR",
4937
"UCHAR",
5038
"SCHAR",
@@ -85,5 +73,20 @@ datatype.enum = [
8573
"BOOL",
8674
]
8775

76+
[oneOf.patternProperties.".*".else]
77+
title = "A generic attribute - short form"
78+
anyOf = [
79+
# Any primitive value
80+
{ not = { anyOf = [
81+
{ type = "object", title = "An object" },
82+
{ type = "array", title = "An array" },
83+
] }, title = "No complex type" },
84+
# Or an array of any primitive value
85+
{ type = "array", items = { not = { anyOf = [
86+
{ type = "object", title = "An object" },
87+
{ type = "array", title = "An array" },
88+
] } }, title = "An array of non-complex types" },
89+
]
90+
8891
[oneOf.propertyNames]
8992
pattern = "^\\w*$"

share/openPMD/json_schema/mesh.toml

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,38 @@ title = "Contains components"
6464
# Requirement 2.1: Either this is a scalar mesh... #
6565
####################################################
6666

67-
[[allOf.oneOf]]
67+
[allOf.if]
68+
anyOf = [
69+
# vector mesh
70+
{ required = [
71+
"datatype",
72+
] },
73+
# constant mesh
74+
{ required = [
75+
"attributes",
76+
], properties.attributes.required = [
77+
"shape",
78+
"value",
79+
] },
80+
]
81+
82+
83+
[allOf.then]
6884
title = "Scalar mesh component"
6985
"$ref" = "mesh_record_component.json"
7086

71-
#################################################
72-
# Requirement 2.2: ... or it's a vector mesh. #
73-
# Note that exactly one of these two conditions #
74-
# must be true, not both at once (oneOf). #
75-
#################################################
87+
###############################################
88+
# Requirement 2.2: ... or it's a vector mesh. #
89+
###############################################
7690

77-
[[allOf.oneOf]]
91+
[allOf.else]
7892
title = "Vector component"
7993
description = "Additionally to the attributes, at least one component must be contained"
8094
# The attributes are contained in this dict, and at least one further
8195
# non-scalar component. Hence, we require at least two entries.
8296
minProperties = 2
8397
propertyNames.pattern = "^\\w*$"
8498

85-
[allOf.oneOf.patternProperties."^(?!attributes).*"]
99+
[allOf.else.patternProperties."^(?!attributes).*"]
86100
title = "Vector mesh component"
87101
"$ref" = "mesh_record_component.json"

share/openPMD/json_schema/record.toml

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,37 @@ title = "Contains components"
4747
# Requirement 2.1: Either this is a scalar mesh... #
4848
####################################################
4949

50-
[[allOf.oneOf]]
50+
[allOf.if]
51+
anyOf = [
52+
# vector mesh
53+
{ required = [
54+
"datatype",
55+
] },
56+
# constant mesh
57+
{ required = [
58+
"attributes",
59+
], properties.attributes.required = [
60+
"shape",
61+
"value",
62+
] },
63+
]
64+
65+
[allOf.then]
5166
title = "Scalar component"
5267
"$ref" = "record_component.json"
5368

54-
#################################################
55-
# Requirement 2.2: ... or it's a vector mesh. #
56-
# Note that exactly one of these two conditions #
57-
# must be true, not both at once (oneOf). #
58-
#################################################
69+
###############################################
70+
# Requirement 2.2: ... or it's a vector mesh. #
71+
###############################################
5972

60-
[[allOf.oneOf]]
73+
[allOf.else]
6174
title = "Vector component"
6275
description = "Additionally to the attributes, at least one component must be contained"
6376
# The attributes are contained in this dict, and at least one further
6477
# non-scalar component. Hence, we require at least two entries.
6578
minProperties = 2
6679
propertyNames.pattern = "^\\w*$"
6780

68-
[allOf.oneOf.patternProperties]
69-
70-
[allOf.oneOf.patternProperties."^(?!attributes).*"]
81+
[allOf.else.patternProperties."^(?!attributes).*"]
7182
title = "Scalar component"
7283
"$ref" = "record_component.json"

0 commit comments

Comments
 (0)