Skip to content

Commit f535cc6

Browse files
[DependencyInjection][Routing] Add JSON schema for validating and autocompleting YAML config files
1 parent 693311f commit f535cc6

File tree

2 files changed

+488
-0
lines changed

2 files changed

+488
-0
lines changed
Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"title": "Symfony Parameters and Services Configuration",
4+
"description": "Defines application parameters and services, including imports and environment-specific conditionals.",
5+
"$comment": "Root allows extension namespaces (framework:, doctrine:, etc.) via additionalProperties: true.",
6+
"type": "object",
7+
"properties": {
8+
"imports": {
9+
"type": "array",
10+
"description": "Import other configuration resources.",
11+
"$comment": "YAML examples:\n- { resource: 'services.yaml' }\n- { resource: packages/dev/services.yaml, ignore_errors: true }\n- 'other_file.yaml'",
12+
"items": {
13+
"oneOf": [
14+
{ "type": "string" },
15+
{
16+
"type": "object",
17+
"properties": {
18+
"resource": { "type": "string" },
19+
"type": { "type": ["string", "null"] },
20+
"ignore_errors": { "type": "boolean" }
21+
},
22+
"required": ["resource"],
23+
"additionalProperties": false
24+
}
25+
]
26+
}
27+
},
28+
"parameters": {
29+
"type": "object",
30+
"description": "Defines application-wide parameters.",
31+
"$comment": "Values support scalars, arrays and objects.",
32+
"patternProperties": {
33+
"^.*$": { "$ref": "#/$defs/parameterValue" }
34+
},
35+
"additionalProperties": false
36+
},
37+
"services": {
38+
"type": "object",
39+
"description": "Defines your application services.",
40+
"$comment": "Service ids accept multiple shapes: object (full definition), '@alias' string (alias), null (empty definition), prototype (resource/namespace), stack, and short array syntax for arguments.",
41+
"properties": {
42+
"_defaults": {
43+
"$ref": "#/$defs/serviceDefaults"
44+
},
45+
"_instanceof": {
46+
"type": "object",
47+
"patternProperties": {
48+
"^.+$": { "$ref": "#/$defs/serviceInstanceof" }
49+
},
50+
"additionalProperties": false
51+
}
52+
},
53+
"patternProperties": {
54+
"^(?:[A-Za-z_\\x7f-\\xff][A-Za-z0-9_\\x7f-\\xff]*\\\\)+[A-Za-z_\\x7f-\\xff][A-Za-z0-9_\\x7f-\\xff]*$": {
55+
"oneOf": [
56+
{ "$ref": "#/$defs/serviceConcrete" },
57+
{ "$ref": "#/$defs/serviceAliasObject" },
58+
{ "$ref": "#/$defs/servicePrototype" },
59+
{ "$ref": "#/$defs/serviceStack" },
60+
{ "$ref": "#/$defs/serviceShortSyntax" },
61+
{ "type": "null" },
62+
{ "type": "string", "pattern": "^@.+" }
63+
],
64+
"$comment": "FQCN service ids: short array syntax is allowed here."
65+
},
66+
"^(?!_).+$": {
67+
"oneOf": [
68+
{ "$ref": "#/$defs/serviceConcrete" },
69+
{ "$ref": "#/$defs/serviceAliasObject" },
70+
{ "$ref": "#/$defs/servicePrototype" },
71+
{ "$ref": "#/$defs/serviceStack" },
72+
{ "type": "null" },
73+
{ "type": "string", "pattern": "^@.+" }
74+
],
75+
"$comment": "Non-FQCN ids: short array syntax is not allowed."
76+
}
77+
},
78+
"additionalProperties": false
79+
}
80+
},
81+
"patternProperties": {
82+
"^when@.+$": {
83+
"$ref": "#",
84+
"description": "A container for parameters and services that are only loaded in a specific environment."
85+
}
86+
},
87+
"additionalProperties": true,
88+
"$defs": {
89+
"parameterValue": {
90+
"oneOf": [
91+
{ "type": "string" },
92+
{ "type": "number" },
93+
{ "type": "boolean" },
94+
{ "type": "array" },
95+
{ "type": "object" },
96+
{ "type": "null" }
97+
]
98+
},
99+
"scalarValue": {
100+
"oneOf": [
101+
{ "type": "string" },
102+
{ "type": "number" },
103+
{ "type": "boolean" },
104+
{ "type": "null" }
105+
]
106+
},
107+
"fqcn": {
108+
"type": "string",
109+
"pattern": "^(?:\\\\)?(?:[A-Za-z_\\\\x7f-\\\\xff][A-Za-z0-9_\\\\x7f-\\\\xff]*\\\\)+[A-Za-z_\\\\x7f-\\\\xff][A-Za-z0-9_\\\\x7f-\\\\xff]*$",
110+
"$comment": "Fully-qualified class name, optional leading backslash; requires at least one namespace separator."
111+
},
112+
"arguments": {
113+
"$comment": "Arguments can be an array (positional) or a map (named).",
114+
"oneOf": [
115+
{ "type": "array", "items": { "$ref": "#/$defs/parameterValue" } },
116+
{ "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } }
117+
]
118+
},
119+
"tags": {
120+
"$comment": "YAML examples:\n- ['kernel.event_subscriber', { name: 'kernel.event_listener', event: 'kernel.request' }, { my_tag: { attr: 1 } }].",
121+
"type": "array",
122+
"items": {
123+
"oneOf": [
124+
{ "type": "string" },
125+
{
126+
"type": "object",
127+
"properties": { "name": { "type": "string" } },
128+
"required": ["name"],
129+
"additionalProperties": true
130+
},
131+
{
132+
"type": "object",
133+
"minProperties": 1,
134+
"maxProperties": 1,
135+
"additionalProperties": {
136+
"type": "object",
137+
"additionalProperties": { "$ref": "#/$defs/parameterValue" }
138+
}
139+
}
140+
]
141+
}
142+
},
143+
"calls": {
144+
"$comment": "YAML examples:\n- ['setFoo', ['@bar'], true]\n- { method: 'setFoo', arguments: ['@bar'], returns_clone: true }\n- { setFoo: ['@bar'] }\n- { setFoo: !returns_clone ['@bar'] } (special YAML tag)",
145+
"type": "array",
146+
"items": {
147+
"oneOf": [
148+
{
149+
"type": "array",
150+
"minItems": 1,
151+
"maxItems": 3,
152+
"items": [
153+
{ "type": "string" },
154+
{
155+
"oneOf": [
156+
{ "type": "array", "items": { "$ref": "#/$defs/parameterValue" } },
157+
{ "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } }
158+
]
159+
},
160+
{ "type": "boolean" }
161+
]
162+
},
163+
{
164+
"type": "object",
165+
"properties": {
166+
"method": { "type": "string" },
167+
"arguments": { "$ref": "#/$defs/arguments" },
168+
"returns_clone": { "type": "boolean" }
169+
},
170+
"required": ["method"],
171+
"additionalProperties": false
172+
},
173+
{
174+
"type": "object",
175+
"minProperties": 1,
176+
"maxProperties": 1,
177+
"additionalProperties": { "$ref": "#/$defs/arguments" }
178+
}
179+
]
180+
}
181+
},
182+
"deprecation": {
183+
"$comment": "YamlFileLoader requires an object with 'package' and 'version'.",
184+
"type": "object",
185+
"properties": {
186+
"package": { "type": "string" },
187+
"version": { "type": "string" },
188+
"message": { "type": "string" }
189+
},
190+
"required": ["package", "version"],
191+
"additionalProperties": false
192+
},
193+
"callable": {
194+
"$comment": "Either 'Class::method' or ['Class', 'method'].",
195+
"oneOf": [
196+
{ "type": "string" },
197+
{
198+
"type": "array",
199+
"minItems": 2,
200+
"maxItems": 2,
201+
"items": [ { "type": "string" }, { "type": "string" } ]
202+
}
203+
]
204+
},
205+
"serviceShortSyntax": {
206+
"$comment": "Short syntax: service defined as arguments array. YAML example: my.service: ['@dependency', 'literal', 123]",
207+
"type": "array",
208+
"items": { "$ref": "#/$defs/parameterValue" }
209+
},
210+
"factoryCallable": {
211+
"$comment": "Either '@service', 'Class::method', or [classOrService, method]. For ['null', method] the class is resolved from the service class when using 'constructor'.",
212+
"oneOf": [
213+
{ "type": "string" },
214+
{
215+
"type": "array",
216+
"minItems": 2,
217+
"maxItems": 2,
218+
"items": [ { "type": ["string", "null"] }, { "type": "string" } ]
219+
}
220+
]
221+
},
222+
"serviceAliasObject": {
223+
"$comment": "Allowed keys for aliases are only 'alias', 'public', 'deprecated'.",
224+
"type": "object",
225+
"properties": {
226+
"alias": { "type": "string" },
227+
"public": { "type": "boolean" },
228+
"deprecated": { "$ref": "#/$defs/deprecation" }
229+
},
230+
"required": ["alias"],
231+
"additionalProperties": false
232+
},
233+
"serviceConcrete": {
234+
"$comment": "'constructor' cannot be used together with 'factory'. If 'from_callable' is used, many other keys are not allowed (see YamlFileLoader).",
235+
"type": "object",
236+
"properties": {
237+
"class": { "type": "string" },
238+
"file": { "type": "string" },
239+
"parent": { "type": "string" },
240+
"shared": { "type": "boolean" },
241+
"synthetic": { "type": "boolean" },
242+
"lazy": { "oneOf": [ { "type": "boolean" }, { "$ref": "#/$defs/fqcn" } ] },
243+
"public": { "type": "boolean" },
244+
"abstract": { "type": "boolean" },
245+
"deprecated": { "$ref": "#/$defs/deprecation" },
246+
"factory": { "$ref": "#/$defs/factoryCallable" },
247+
"configurator": { "$ref": "#/$defs/callable" },
248+
"arguments": { "$ref": "#/$defs/arguments" },
249+
"properties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
250+
"calls": { "$ref": "#/$defs/calls" },
251+
"tags": { "$ref": "#/$defs/tags" },
252+
"decorates": { "type": "string" },
253+
"decoration_inner_name": { "type": "string" },
254+
"decoration_priority": { "type": "integer" },
255+
"decoration_on_invalid": { "oneOf": [ { "enum": ["exception", "ignore"] }, { "type": "null" } ], "$comment": "Use null (without quotes) for NULL_ON_INVALID_REFERENCE." },
256+
"autowire": { "type": "boolean" },
257+
"autoconfigure": { "type": "boolean" },
258+
"bind": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
259+
"constructor": { "type": "string" },
260+
"from_callable": { "$ref": "#/$defs/parameterValue", "$comment": "Will be wrapped by factory ['Closure','fromCallable'] and sets lazy=true unless class is 'Closure'." }
261+
},
262+
"additionalProperties": false
263+
},
264+
"servicePrototype": {
265+
"$comment": "Prototype definitions register classes by scanning directories. 'namespace' requires 'resource'.",
266+
"type": "object",
267+
"properties": {
268+
"resource": { "type": "string" },
269+
"namespace": { "type": "string" },
270+
"exclude": {
271+
"oneOf": [
272+
{ "type": "string" },
273+
{ "type": "array", "items": { "type": "string" } }
274+
]
275+
},
276+
"parent": { "type": "string" },
277+
"shared": { "type": "boolean" },
278+
"lazy": { "oneOf": [ { "type": "boolean" }, { "$ref": "#/$defs/fqcn" } ] },
279+
"public": { "type": "boolean" },
280+
"abstract": { "type": "boolean" },
281+
"deprecated": { "$ref": "#/$defs/deprecation" },
282+
"factory": { "$ref": "#/$defs/factoryCallable" },
283+
"arguments": { "$ref": "#/$defs/arguments" },
284+
"properties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
285+
"configurator": { "$ref": "#/$defs/callable" },
286+
"calls": { "$ref": "#/$defs/calls" },
287+
"tags": { "$ref": "#/$defs/tags" },
288+
"autowire": { "type": "boolean" },
289+
"autoconfigure": { "type": "boolean" },
290+
"bind": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
291+
"constructor": { "type": "string" }
292+
},
293+
"required": ["resource"],
294+
"allOf": [
295+
{ "anyOf": [ { "not": { "required": ["namespace"] } }, { "required": ["resource"] } ] }
296+
],
297+
"additionalProperties": false
298+
},
299+
"serviceStack": {
300+
"$comment": "A stack builds a service pipeline from multiple frames.",
301+
"type": "object",
302+
"properties": {
303+
"stack": {
304+
"type": "array",
305+
"items": {
306+
"oneOf": [
307+
{ "$ref": "#/$defs/serviceConcrete" },
308+
{ "$ref": "#/$defs/serviceAliasObject" },
309+
{ "$ref": "#/$defs/servicePrototype" }
310+
]
311+
}
312+
},
313+
"public": { "type": "boolean" },
314+
"deprecated": { "$ref": "#/$defs/deprecation" }
315+
},
316+
"required": ["stack"],
317+
"additionalProperties": false
318+
},
319+
"serviceDefaults": {
320+
"$comment": "Defaults applied to services declared in the current file.",
321+
"type": "object",
322+
"properties": {
323+
"public": { "type": "boolean" },
324+
"tags": { "$ref": "#/$defs/tags" },
325+
"autowire": { "type": "boolean" },
326+
"autoconfigure": { "type": "boolean" },
327+
"bind": {
328+
"type": "object",
329+
"additionalProperties": { "$ref": "#/$defs/parameterValue" }
330+
}
331+
},
332+
"additionalProperties": false
333+
},
334+
"serviceInstanceof": {
335+
"$comment": "Applied to services declared in the current file whose class matches the key (interface or parent class).",
336+
"type": "object",
337+
"properties": {
338+
"shared": { "type": "boolean" },
339+
"lazy": { "oneOf": [ { "type": "boolean" }, { "$ref": "#/$defs/fqcn" } ] },
340+
"public": { "type": "boolean" },
341+
"properties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
342+
"configurator": { "$ref": "#/$defs/callable" },
343+
"calls": { "$ref": "#/$defs/calls" },
344+
"tags": { "$ref": "#/$defs/tags" },
345+
"autowire": { "type": "boolean" },
346+
"bind": { "type": "object", "additionalProperties": { "$ref": "#/$defs/parameterValue" } },
347+
"constructor": { "type": "string" }
348+
},
349+
"additionalProperties": false
350+
}
351+
}
352+
}

0 commit comments

Comments
 (0)