Formato NEON

NEON es un formato de datos estructurados legible por humanos. En Nette se usa para los archivos de configuración. También se usa para datos estructurados como ajustes, traducciones de idiomas, etc. Pruébelo en el sandbox.

NEON significa Nette Object Notation. Es menos complejo y engorroso que XML o JSON, pero ofrece capacidades parecidas. Se parece mucho a YAML. Su principal ventaja es que NEON tiene las llamadas entidades, gracias a las cuales la configuración de los servicios DI resulta tan sexy. Y permite tabuladores para la indentación.

NEON está construido desde cero para ser fácil de usar.

Integración

Sintaxis

Un archivo escrito en NEON suele representar una secuencia o un mapeo.

Mapeos

Un mapeo es un conjunto de pares clave-valor; en PHP se llamaría array asociativo. Cada par se escribe como clave: valor, y el espacio tras : es obligatorio. El valor puede ser cualquier cosa: cadena, número, booleano, null, secuencia u otro mapeo.

street: 742 Evergreen Terrace
city: Springfield
country: USA

En PHP, la misma estructura se escribiría así:

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

Esta notación se llama notación de bloque porque todos los elementos están en líneas separadas y tienen la misma indentación (ninguna, en este caso). NEON soporta también una representación en línea para los mapeos, que va entre llaves, donde la indentación no importa y el separador de los elementos es una coma o un salto de línea:

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

Lo mismo escrito en varias líneas (la indentación no importa):

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

Como alternativa se puede usar = en lugar de : , tanto en la notación de bloque como en la de línea:

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

Secuencias

Las secuencias son los arrays indexados de PHP. Se escriben como líneas que empiezan con un guion - seguido de un espacio. También aquí el valor puede ser cualquier cosa: cadena, número, booleano, null, secuencia u otro mapeo.

- Cat
- Dog
- Goldfish

En PHP, la misma estructura se escribiría así:

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

Esta notación se llama notación de bloque porque todos los elementos están en líneas separadas y tienen la misma indentación (ninguna, en este caso). NEON soporta también una representación en línea para las secuencias, que va entre corchetes, donde la indentación no importa y el separador de los elementos es una coma o un salto de línea:

[Cat, Dog, Goldfish]

Lo mismo escrito en varias líneas (la indentación no importa):

[
	Cat, Dog
		Goldfish
]

En la representación en línea no se pueden usar los guiones (viñetas).

Combinaciones

Los valores de los mapeos y de las secuencias pueden ser otros mapeos y secuencias. El nivel de indentación juega un papel fundamental. En el ejemplo siguiente, el guion que marca los elementos de la secuencia tiene mayor indentación que la clave pets, así que los elementos pasan a ser el valor de la primera línea:

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

En PHP, la misma estructura se escribiría así:

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

Es posible combinar la notación de bloque con la de línea:

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

La notación de bloque no se puede usar dentro de una notación en línea; esto no funciona:

item: [
	pets:
	 - Cat     # ¡¡¡ESTO NO ES POSIBLE!!!
	 - Dog
]

En el caso anterior escribimos un mapeo cuyos elementos eran secuencias. Probemos ahora al revés y creemos una secuencia que contenga mapeos:

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

No hace falta que los guiones estén en líneas separadas; también se pueden colocar así:

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

Usted decide si alinea las claves en una columna con espacios o usa un tabulador.

Como PHP usa la misma estructura para los mapeos y las secuencias (es decir, arrays), ambos se pueden mezclar. Esta vez la indentación es la misma:

- Cat
street: 742 Evergreen Terrace
- Goldfish

En PHP, la misma estructura se escribiría así:

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

Cadenas

Las cadenas en NEON se pueden encerrar entre comillas simples o dobles. Pero, como ve, también pueden ir sin comillas.

- Una cadena sin comillas en NEON
- 'Una cadena entre comillas simples en NEON'
- "Una cadena entre comillas dobles en NEON"

Si la cadena contiene los caracteres ` # " ' ` , : = - [ ] { } ( ) `, que se podrían confundir con la sintaxis de NEON, hay que encerrarla entre comillas. Recomendamos usar comillas simples, porque no usan escapado. Si necesita incluir una comilla dentro de una cadena así, dupliquela:

'Una comilla simple '' dentro de una cadena entre comillas simples'

Las comillas dobles permiten usar secuencias de escape para escribir caracteres especiales con barras invertidas \. Se soportan todas las secuencias de escape que soporta el formato JSON, además de \_, que representa un espacio de no separación, es decir, \u00A0.

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

Hay otros casos en los que hay que encerrar las cadenas entre comillas:

  • si empiezan o terminan con espacios
  • si parecen números, booleanos o null
  • si NEON las interpretaría como fechas

Cadenas multilínea

Una cadena multilínea empieza y termina con comillas triples en líneas separadas. La indentación de la primera línea se ignora en todas las líneas:

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

En PHP escribiríamos lo mismo así:

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

Las secuencias de escape funcionan solo en las cadenas encerradas entre comillas dobles en lugar de apóstrofos:

"""
	Copyright \u00A9
"""

Números

NEON entiende los números escritos en notación científica y también los números en base binaria, octal y hexadecimal:

- 12         # número entero
- 12.3       # número decimal
- +1.2e-34   # número exponencial

- 0b11010    # número binario
- 0o666      # número octal
- 0x7A       # número hexadecimal

Nulos

El null se puede expresar en NEON con null o dejando el valor vacío. También se permiten las variantes con la primera letra mayúscula o todas las letras mayúsculas (Null, NULL).

a: null
b:

Booleanos

Los valores booleanos se expresan en NEON con true / false o yes / no. También se permiten las variantes con la primera letra mayúscula o todas las letras mayúsculas (True, TRUE, False, FALSE, Yes, YES, No, NO).

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

Fechas

NEON usa los siguientes formatos para expresar fechas y las convierte automáticamente en objetos DateTimeImmutable:

- 2016-06-03                  # fecha
- 2016-06-03 19:00:00         # fecha y hora
- 2016-06-03 19:00:00.1234    # fecha y hora con microsegundos
- 2016-06-03 19:00:00 +0200   # fecha, hora y zona horaria
- 2016-06-03 19:00:00 +02:00  # fecha, hora y zona horaria

Entidades

Una entidad es una estructura que recuerda a una llamada a una función:

Column(type: int, nulls: yes)

En PHP se parsea como un objeto Nette\Neon\Entity:

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

Las entidades también se pueden encadenar:

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

Lo que en PHP se parsea así:

// 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]),
])

Dentro de los paréntesis rigen las reglas de la notación en línea que se usa para los mapeos y las secuencias, así que puede ser multilínea y las comas no son necesarias:

Column(
	type: int
	nulls: yes
)

Comentarios

Los comentarios empiezan con # y todos los caracteres que siguen a su derecha se ignoran:

# el intérprete ignorará esta línea
street: 742 Evergreen Terrace
city: Springfield  # esto también se ignora
country: USA

NEON frente a JSON

JSON es un subconjunto de NEON. Por tanto, cualquier JSON se puede parsear como NEON:

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

¿Y si omitiéramos las comillas?

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

¿Y qué tal las llaves y las comas?

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

database:
	driver: mysql
	username: root
	password: password123

users: [
	Dave, Kryten, Rimmer
]

¿No son más legibles las listas con viñetas?

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

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

¿Añadimos comentarios?

# configuración de mi aplicación web

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

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

¡Bravo, ya conoce la sintaxis de NEON!

versión: 3.x