Format NEON

NEON est un format de données structurées lisible par l'humain. Nette l'utilise pour les fichiers de configuration. Il sert aussi pour des données structurées comme les réglages, les traductions, etc. Essayez-le dans le bac à sable.

NEON signifie Nette Object Notation. Il est moins complexe et moins lourd que XML ou JSON, tout en offrant des possibilités comparables. Il ressemble beaucoup à YAML. Son principal atout, ce sont les Entités, grâce auxquelles la configuration des services DI est si sexy. Et il autorise les tabulations pour l'indentation.

NEON a été conçu dès le départ pour être simple à utiliser.

Intégration

Syntaxe

Un fichier écrit en NEON représente d'ordinaire une séquence ou un mapping.

Mappings

Un mapping est un ensemble de paires clé-valeur ; en PHP, on parlerait de tableau associatif. Chaque paire s'écrit clé: valeur, et l'espace après : est obligatoire. La valeur peut être n'importe quoi : chaîne, nombre, booléen, null, séquence ou un autre mapping.

street: 742 Evergreen Terrace
city: Springfield
country: USA

En PHP, la même structure s'écrirait :

[ // PHP
	'street' => '742 Evergreen Terrace',
	'city' => 'Springfield',
	'country' => 'USA',
]

Cette écriture est dite en bloc, car tous les éléments sont sur des lignes distinctes et partagent la même indentation (ici aucune). NEON accepte aussi une représentation inline du mapping, entourée d'accolades, où l'indentation ne joue aucun rôle et où le séparateur des éléments est soit la virgule, soit le passage à la ligne :

{street: 742 Evergreen Terrace, city: Springfield, country: USA}

La même chose écrite sur plusieurs lignes (l'indentation n'a pas d'importance) :

{
	street: 742 Evergreen Terrace
		city: Springfield, country: USA
}

On peut aussi employer = à la place de : , aussi bien en écriture bloc qu'inline :

{street=742 Evergreen Terrace, city=Springfield, country=USA}

Séquences

Les séquences sont les tableaux indexés de PHP. Elles s'écrivent sous forme de lignes commençant par un tiret - suivi d'une espace. Là encore, la valeur peut être n'importe quoi : chaîne, nombre, booléen, null, séquence ou un mapping.

- Cat
- Dog
- Goldfish

En PHP, la même structure s'écrirait :

[ // PHP
	'Cat',
	'Dog',
	'Goldfish',
]

Cette écriture est dite en bloc, car tous les éléments sont sur des lignes distinctes et partagent la même indentation (ici aucune). NEON accepte aussi une représentation inline des séquences, entourée de crochets, où l'indentation ne joue aucun rôle et où le séparateur des éléments est soit la virgule, soit le passage à la ligne :

[Cat, Dog, Goldfish]

La même chose écrite sur plusieurs lignes (l'indentation n'a pas d'importance) :

[
	Cat, Dog
		Goldfish
]

Les tirets (puces) ne peuvent pas être utilisés dans la représentation inline.

Combinaisons

Les valeurs des mappings et des séquences peuvent être d'autres mappings et séquences. Le niveau d'indentation y joue un rôle déterminant. Dans l'exemple suivant, le tiret marquant les éléments de la séquence est plus indenté que la clé pets, si bien que les éléments deviennent la valeur de la première ligne :

pets:
   - Cat
   - Dog
cars:
   - Volvo
   - Skoda

En PHP, la même structure s'écrirait :

[ // PHP
	'pets' => [
		'Cat',
		'Dog',
	],
	'cars' => [
		'Volvo',
		'Skoda',
	],
]

Il est possible de combiner l'écriture bloc et l'écriture inline :

pets: [Cat, Dog]
cars: [
	Volvo,
	Skoda,
]

En revanche, l'écriture bloc ne peut pas être utilisée à l'intérieur d'une écriture inline ; ceci ne fonctionne pas :

item: [
	pets:
	 - Cat     # THIS IS NOT POSSIBLE!!!
	 - Dog
]

Dans le cas précédent, nous avons écrit un mapping dont les éléments étaient des séquences. Essayons maintenant l'inverse et créons une séquence contenant des mappings :

-
	name: John
	age: 35
-
	name: Peter
	age: 28

Les tirets n'ont pas besoin d'être sur des lignes séparées ; on peut aussi les placer ainsi :

- name: John
  age: 35
- name: Peter
  age: 28

Libre à vous d'aligner les clés en colonne avec des espaces ou d'utiliser une tabulation.

Comme PHP emploie la même structure pour les mappings et les séquences (à savoir le tableau), les deux peuvent être fusionnés. Cette fois, l'indentation est identique :

- Cat
street: 742 Evergreen Terrace
- Goldfish

En PHP, la même structure s'écrirait :

[ // PHP
	'Cat',
	'street' => '742 Evergreen Terrace',
	'Goldfish',
]

Chaînes

En NEON, les chaînes peuvent être entourées d'apostrophes ou de guillemets. Mais comme vous le voyez, elles peuvent aussi s'en passer.

- An unquoted string in NEON
- 'A single-quoted string in NEON'
- "A double-quoted string in NEON"

Si la chaîne contient les caractères ` # " ' ` , : = - [ ] { } ( ) ` qui pourraient être confondus avec la syntaxe NEON, elle doit être entourée de guillemets. Nous recommandons les apostrophes, car elles n'utilisent pas d'échappement. Si vous devez placer une apostrophe dans une telle chaîne, doublez-la :

'A single quote '' inside a single-quoted string'

Les guillemets doubles permettent d'employer des séquences d'échappement pour écrire des caractères spéciaux à l'aide de la barre oblique inverse \. Toutes les séquences d'échappement du format JSON sont prises en charge, plus \_, qui représente l'espace insécable, c'est-à-dire \u00A0.

- "\t \n \r \f \b \" \\ \/ \_"
- "\u00A9"

Il existe d'autres cas où il faut entourer les chaînes de guillemets :

  • elles commencent ou finissent par des espaces
  • elles ressemblent à des nombres, des booléens ou à null
  • NEON les interpréterait comme des Dates

Chaînes multilignes

Une chaîne multiligne commence et se termine par un triple guillemet sur des lignes distinctes. L'indentation de la première ligne est ignorée pour toutes les lignes :

'''
	first line
		second line
	third line
	'''

En PHP, nous écririons la même chose ainsi :

"first line\n\tsecond line\nthird line" // PHP

Les séquences d'échappement ne fonctionnent que pour les chaînes entourées de guillemets doubles, et non d'apostrophes :

"""
	Copyright \u00A9
"""

Nombres

NEON comprend les nombres écrits en notation scientifique, ainsi que les nombres en base binaire, octale et hexadécimale :

- 12         # integer
- 12.3       # float
- +1.2e-34   # exponential number

- 0b11010    # binary number
- 0o666      # octal number
- 0x7A       # hexadecimal number

Nulls

En NEON, null s'exprime par null ou en omettant la valeur. Les variantes avec majuscule initiale ou tout en majuscules sont également admises (Null, NULL).

a: null
b:

Booléens

Les valeurs booléennes s'expriment en NEON par true / false ou yes / no. Les variantes avec majuscule initiale ou tout en majuscules sont également admises (True, TRUE, False, FALSE, Yes, YES, No, NO).

[true, TRUE, True, false, yes, no]

Dates

NEON utilise les formats suivants pour exprimer les dates et les convertit automatiquement en objets DateTimeImmutable :

- 2016-06-03                  # date
- 2016-06-03 19:00:00         # date & time
- 2016-06-03 19:00:00.1234    # date & microtime
- 2016-06-03 19:00:00 +0200   # date & time & timezone
- 2016-06-03 19:00:00 +02:00  # date & time & timezone

Entités

Une entité est une structure qui rappelle un appel de fonction :

Column(type: int, nulls: yes)

En PHP, elle est analysée comme un objet Nette\Neon\Entity :

// PHP
new Nette\Neon\Entity('Column', ['type' => 'int', 'nulls' => true])

Les entités peuvent aussi être chaînées :

Column(type: int, nulls: yes) Field(id: 1)

Ce qui est analysé en PHP comme suit :

// PHP
new Nette\Neon\Entity(Nette\Neon\Neon::Chain, [
	new Nette\Neon\Entity('Column', ['type' => 'int', 'nulls' => true]),
	new Nette\Neon\Entity('Field', ['id' => 1]),
])

À l'intérieur des parenthèses s'appliquent les règles de l'écriture inline des mappings et des séquences, si bien qu'elle peut tenir sur plusieurs lignes et que les virgules ne sont pas nécessaires :

Column(
	type: int
	nulls: yes
)

Commentaires

Les commentaires commencent par # et tous les caractères qui suivent à droite sont ignorés :

# this line will be ignored by the interpreter
street: 742 Evergreen Terrace
city: Springfield  # this is ignored too
country: USA

NEON face à JSON

JSON est un sous-ensemble de NEON. N'importe quel JSON peut donc être analysé comme du NEON :

{
"php": {
	"date.timezone": "Europe\/Prague",
	"zlib.output_compression": true
},
"database": {
	"driver": "mysql",
	"username": "root",
	"password": "password123"
},
"users": [
	"Dave", "Kryten", "Rimmer"
]
}

Et si nous enlevions les guillemets ?

{
php: {
	date.timezone: Europe/Prague,
	zlib.output_compression: true
},
database: {
	driver: mysql,
	username: root,
	password: password123
},
users: [
	Dave, Kryten, Rimmer
]
}

Et les accolades et les virgules ?

php:
	date.timezone: Europe/Prague
	zlib.output_compression: true

database:
	driver: mysql
	username: root
	password: password123

users: [
	Dave, Kryten, Rimmer
]

Les listes à puces ne sont-elles pas plus lisibles ?

php:
	date.timezone: Europe/Prague
	zlib.output_compression: true

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

Et si nous ajoutions des commentaires ?

# my web application config

php:
	date.timezone: Europe/Prague
	zlib.output_compression: true  # use gzip

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

Hourra, vous connaissez maintenant la syntaxe NEON !

version: 3.x