Formát NEON
***********
.[perex]
NEON je lidsky čitelný strukturovaný datový formát. V Nette se používá pro konfigurační soubory. Také se používá pro strukturovaná data, jako jsou nastavení, jazykové překlady atd. [Vyzkoušejte si jej|https://fiddle.nette.org/neon/].
NEON je zkratka pro *Nette Object Notation*. Je méně složitý a nemotorný než XML nebo JSON, ale poskytuje podobné funkce. Je velmi podobný YAML. Hlavní předností je to, že NEON má takzvané [#entity], díky kterým je konfigurace DI služeb [taky sexy |https://gist.github.com/dg/26baf3ce8f29d0f751e9dddfaa06504f]. A umožňuje odsazovat tabulátory.
NEON je postaven od základů tak, aby byl snadno použitelný. Knihovny pro PHP, JavaScript a Python, podporu v editorech a specifikaci formátu najdete na stránce [Nástroje a knihovny |tools].
Syntaxe
=======
Soubor psaný v NEON obvykle představuje pole nebo mapování.
Mapování
--------
Mapování je sada párů klíč-hodnota, v PHP by se řeklo asociativní pole. Každá dvojice je zapsána jako `key: value`, mezera za `:` je nutná. Hodnotou může být cokoliv: řetězec, číslo, boolean, null, sekvence nebo jiné mapování.
```neon
street: 742 Evergreen Terrace
city: Springfield
country: USA
```
V PHP by se stejná struktura zapsala jako:
```php
[ // PHP
'street' => '742 Evergreen Terrace',
'city' => 'Springfield',
'country' => 'USA',
]
```
Tento zápis se označuje jako blokový, protože všechny položky jsou na samostatném řádku a mají stejné odsazení (v tomto případě žádné). NEON podporuje také inline reprezentaci mapování, která je uzavřená do závorek, odsazení nehraje žádnou roli a oddělovačem jednotlivých prvků je buď čárka, nebo nový řádek:
```neon
{street: 742 Evergreen Terrace, city: Springfield, country: USA}
```
Totéž zapsané na více řádcích (na odsazení nezáleží):
```neon
{
street: 742 Evergreen Terrace
city: Springfield, country: USA
}
```
Místo <code>: </code> lze alternativně používat `=`, a to jak v blokovém, tak v inline zápisu:
```neon
{street=742 Evergreen Terrace, city=Springfield, country=USA}
```
Sekvence
--------
Sekvence jsou v PHP indexované pole. Zapisují se jako řádky začínající spojovníkem `-` následovaným mezerou. Hodnotou opět může být cokoliv: řetězec, číslo, boolean, null, sekvence nebo jiné mapování.
```neon
- Cat
- Dog
- Goldfish
```
V PHP by se stejná struktura zapsala jako:
```php
[ // PHP
'Cat',
'Dog',
'Goldfish',
]
```
Tento zápis se označuje jako blokový, protože všechny položky jsou na samostatném řádku a mají stejné odsazení (v tomto případě žádné). NEON podporuje také inline reprezentaci sekvence, která je uzavřená do závorek, odsazení nehraje žádnou roli a oddělovačem jednotlivých prvků je buď čárka, nebo nový řádek:
```neon
[Cat, Dog, Goldfish]
```
Totéž zapsané na více řádcích (na odsazení nezáleží):
```neon
[
Cat, Dog
Goldfish
]
```
V inline reprezentaci nelze používat odsazující odrážky.
Kombinace
---------
Hodnotami mapování a sekvencí mohou být jiné mapování a sekvence. Hlavní roli hraje úroveň odsazení. V následujícím příkladu má pomlčka použitá k označení položek sekvence větší odsazení než klíč `pets`, takže se položky stávají hodnotou prvního řádku:
```neon
pets:
- Cat
- Dog
cars:
- Volvo
- Skoda
```
V PHP by se stejná struktura zapsala jako:
```php
[ // PHP
'pets' => [
'Cat',
'Dog',
],
'cars' => [
'Volvo',
'Skoda',
],
]
```
Lze kombinovat blokový a inline zápis:
```neon
pets: [Cat, Dog]
cars: [
Volvo,
Skoda,
]
```
Uvnitř inline zápisu již nelze používat zápis blokový, tohle nefunguje:
```neon
item: [
pets:
- Cat # TOHLE NELZE!!!
- Dog
]
```
V předchozím případě jsme zapsali mapování, jehož prvky byly sekvence, teď to zkusíme obráceně a vytvoříme sekvenci obsahující mapování:
```neon
-
name: John
age: 35
-
name: Peter
age: 28
```
Není nutné, aby odrážky byly na samostatných řádcích, lze je umístit i tímto způsobem:
```neon
- name: John
age: 35
- name: Peter
age: 28
```
Je na vás, jestli klíče zarovnáte do sloupce pomocí mezer nebo použijete tabulátor.
Protože v PHP se používá pro mapování i sekvence stejná struktura, tedy pole, lze obojí sloučit. Odsazení je tentokrát stejné:
```neon
- Cat
street: 742 Evergreen Terrace
- Goldfish
```
V PHP by se stejná struktura zapsala jako:
```php
[ // PHP
'Cat',
'street' => '742 Evergreen Terrace',
'Goldfish',
]
```
Položka bez klíče dostane celočíselný klíč o jedna větší než největší celočíselný klíč před ní, stejně jako v PHP. Takže `{5: Cat, Dog}` dá položce `Dog` klíč 6.
Řetězce
-------
Řetězce v NEON lze uzavřít do jednoduchých i dvojitých uvozovek. Ale jak vidíte, mohou být také bez uvozovek.
```neon
- Řetězec v NEON bez uvozovek
- 'Řetězec v NEON v jednoduchých uvozovkách'
- "Řetězec v NEON ve dvojitých uvozovkách"
```
Pokud řetězec obsahuje znaky `` # " ' ` , : = - [ ] { } ( ) ``, které lze zaměnit s NEON syntaxí, je potřeba jej uzavřít do uvozovek. Doporučujeme použít jednoduché uvozovky, protože v nich se nepoužívá escapování. Pokud potřebujete v takovém řetězci zapsat uvozovku, zdvojte ji:
```neon
'Uvozovka '' uvnitř řetězce v jednoduchých uvozovkách'
```
Dvojité uvozovky umožňují používat escape sekvence pro zápis speciálních znaků pomocí zpětných lomítek `\`. Podporovány jsou všechny escape sekvence jako u formátu JSON a navíc `\_`, což je nedělitelná mezera, tedy `\u00A0`.
```neon
- "\t \n \r \f \b \" \\ \/ \_"
- "\u00A9"
```
Existují další případy, kdy je potřeba uzavřít řetězce do uvozovek:
- začínají či končí mezerami
- vypadají jako čísla, booleany, nebo null
- NEON by je chápal jako [#datum]
Víceřádkové řetězce
-------------------
Víceřádkový řetězec začíná a končí trojitou uvozovkou na samostatných řádcích. Odsazení prvního neprázdného řádku se odstraní ze všech řádků:
```neon
'''
první řádek
druhý řádek
třetí řádek
'''
```
V PHP bychom totéž napsali jako:
```php
"první řádek\n\tdruhý řádek\ntřetí řádek" // PHP
```
Řádek odsazený méně než první neprázdný řádek si své odsazení ponechá celé. Řádek jen z mezer nebo tabulátorů není prázdný, takže pokud je první, určí odsazení on.
Escapovací sekvence fungují jen u řetězců uvozených dvojitými uvozovkami místo apostrofů:
```neon
"""
Copyright \u00A9
"""
```
Zpětné lomítko na konci řádku ho nespojí s dalším řádkem, v řetězci zůstane.
Čísla
-----
NEON rozumí číslům zapsaným v tzv. vědecké notaci a také číslům v binární, osmičkové a hexadecimální soustavě:
```neon
- 12 # celé číslo
- 12.3 # float
- +1.2e-34 # exponenciální číslo
- 0b11010 # binární číslo
- 0o666 # osmičkové číslo
- 0x7A # hexa číslo
```
Předpony `0b`, `0o` a `0x` se píšou malými písmeny a bez znaménka, takže `0X10` a `-0x1` jsou řetězce. Úvodní nuly neznamenají osmičkové číslo: `0777` je 777. Podtržítka mezi číslicemi povolená nejsou, `1_000` je řetězec.
Nulls
-----
Null lze v NEON vyjádřit pomocí `null` nebo neuvedením hodnoty. Povoleny jsou také varianty s velkým prvním nebo velkými všemi písmeny.
```neon
a: null
b:
```
Booleans
--------
Logické hodnoty jsou v NEON vyjádřeny pomocí `true` / `false` nebo `yes` / `no`. Povoleny jsou také varianty s velkým prvním nebo velkými všemi písmeny.
```neon
[true, TRUE, True, false, yes, no]
```
Slova `on` a `off`, která YAML 1.1 čte jako logické hodnoty, jsou v NEONu obyčejné řetězce. .{data-version:3.4.0}
Datum
-----
NEON používá k vyjádření dat následující formáty a automaticky je převede na objekty `DateTimeImmutable`:
```neon
- 2016-06-03 # datum
- 2016-06-03 19:00:00 # datum & čas
- 2016-06-03 19:00:00.1234 # datum & mikročas
- 2016-06-03 19:00:00 +0200 # datum & čas & zóna
- 2016-06-03 19:00:00 +02:00 # datum & čas & zóna
- 2016-06-03T19:00:00Z # ISO 8601 s T a zónou UTC
```
Literál, který vypadá jako datum, ale platným datem není, třeba `2024-02-30`, se nepřevede a zůstane řetězcem.
Entity
------
Entita je struktura, která připomíná volání funkce:
```neon
Column(type: int, nulls: yes)
```
V PHP se naparsuje jako objekt [api:Nette\Neon\Entity]:
```php
// PHP
new Nette\Neon\Entity('Column', ['type' => 'int', 'nulls' => true])
```
Entity se mohou i zřetězit:
```neon
Column(type: int, nulls: yes) Field(id: 1)
```
Což se v PHP naparsuje tímto způsobem:
```php
// 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]),
])
```
Hodnota `Neon::Chain` je `!!chain`, takže toto jméno je vyhrazené a pro vlastní entitu ho použít nelze.
Uvnitř závorek platí pravidla pro inline zápis používaný u mapování a sekvencí, tedy může být klidně i víceřádkový a pak není nutné uvádět čárky:
```neon
Column(
type: int
nulls: yes
)
```
Komentáře
---------
Komentáře začínají znakem `#` a všechny následující znaky napravo jsou ignorovány:
```neon
# this line will be ignored by the interpreter
street: 742 Evergreen Terrace
city: Springfield # this is ignored too
country: USA
```
Neon versus JSON
================
JSON je téměř podmnožinou NEONu, takže prakticky každý JSON se dá parsovat jako NEON. Jedinou výjimkou je dvojtečka na začátku řádku přilepená k hodnotě, třeba `"a"` a pod ním řádek s `:1`, což NEON čte jako řetězec `:1`:
```neon
{
"php": {
"date.timezone": "Europe\/Prague",
"zlib.output_compression": true
},
"database": {
"driver": "mysql",
"username": "root",
"password": "beruska92"
},
"users": [
"Dave", "Kryten", "Rimmer"
]
}
```
Co kdybychom vynechali uvozovky?
```neon
{
php: {
date.timezone: Europe/Prague,
zlib.output_compression: true
},
database: {
driver: mysql,
username: root,
password: beruska92
},
users: [
Dave, Kryten, Rimmer
]
}
```
A složené závorky a čárky?
```neon
php:
date.timezone: Europe/Prague
zlib.output_compression: true
database:
driver: mysql
username: root
password: beruska92
users: [
Dave, Kryten, Rimmer
]
```
Nejsou seznamy s odrážkami lépe čitelné?
```neon
php:
date.timezone: Europe/Prague
zlib.output_compression: true
database:
driver: mysql
username: root
password: beruska92
users:
- Dave
- Kryten
- Rimmer
```
Přidáme komentáře?
```neon
# my web application config
php:
date.timezone: Europe/Prague
zlib.output_compression: true # use gzip
database:
driver: mysql
username: root
password: beruska92
users:
- Dave
- Kryten
- Rimmer
```
Hurá, teď znáte syntaxi NEONu!
{{maintitle: Formát NEON: lidsky čitelná alternativa k YAML a JSON}}
{{description: NEON je snadno čitelný formát pro serializaci dat, podobný YAMLu. Hlavní rozdíl je v tom, že podporuje entity a k odsazování můžete použít i tabulátory.}}
NEON je lidsky čitelný strukturovaný datový formát. V Nette se používá pro konfigurační soubory. Také
se používá pro strukturovaná data, jako jsou nastavení, jazykové překlady atd. Vyzkoušejte si jej.
NEON je zkratka pro Nette Object Notation. Je méně složitý a nemotorný než XML nebo JSON, ale poskytuje podobné
funkce. Je velmi podobný YAML. Hlavní předností je to, že NEON má takzvané entity, díky kterým
je konfigurace DI služeb taky sexy. A umožňuje
odsazovat tabulátory.
NEON je postaven od základů tak, aby byl snadno použitelný. Knihovny pro PHP, JavaScript a Python, podporu v editorech a
specifikaci formátu najdete na stránce Nástroje a knihovny.
Syntaxe
Soubor psaný v NEON obvykle představuje pole nebo mapování.
Mapování
Mapování je sada párů klíč-hodnota, v PHP by se řeklo asociativní pole. Každá dvojice je zapsána jako
key: value, mezera za : je nutná. Hodnotou může být cokoliv: řetězec, číslo, boolean, null,
sekvence nebo jiné mapování.
street: 742 Evergreen Terrace
city: Springfield
country: USA
V PHP by se stejná struktura zapsala jako:
[ // PHP
'street' => '742 Evergreen Terrace',
'city' => 'Springfield',
'country' => 'USA',
]
Tento zápis se označuje jako blokový, protože všechny položky jsou na samostatném řádku a mají stejné odsazení
(v tomto případě žádné). NEON podporuje také inline reprezentaci mapování, která je uzavřená do závorek, odsazení
nehraje žádnou roli a oddělovačem jednotlivých prvků je buď čárka, nebo nový řádek:
{street: 742 Evergreen Terrace, city: Springfield, country: USA}
Totéž zapsané na více řádcích (na odsazení nezáleží):
{
street: 742 Evergreen Terrace
city: Springfield, country: USA
}
Místo : lze alternativně používat =, a to jak v blokovém, tak v inline zápisu:
{street=742 Evergreen Terrace, city=Springfield, country=USA}
Sekvence
Sekvence jsou v PHP indexované pole. Zapisují se jako řádky začínající spojovníkem - následovaným
mezerou. Hodnotou opět může být cokoliv: řetězec, číslo, boolean, null, sekvence nebo jiné mapování.
- Cat
- Dog
- Goldfish
V PHP by se stejná struktura zapsala jako:
[ // PHP
'Cat',
'Dog',
'Goldfish',
]
Tento zápis se označuje jako blokový, protože všechny položky jsou na samostatném řádku a mají stejné odsazení
(v tomto případě žádné). NEON podporuje také inline reprezentaci sekvence, která je uzavřená do závorek, odsazení
nehraje žádnou roli a oddělovačem jednotlivých prvků je buď čárka, nebo nový řádek:
[Cat, Dog, Goldfish]
Totéž zapsané na více řádcích (na odsazení nezáleží):
[
Cat, Dog
Goldfish
]
V inline reprezentaci nelze používat odsazující odrážky.
Kombinace
Hodnotami mapování a sekvencí mohou být jiné mapování a sekvence. Hlavní roli hraje úroveň odsazení.
V následujícím příkladu má pomlčka použitá k označení položek sekvence větší odsazení než klíč
pets, takže se položky stávají hodnotou prvního řádku:
pets:
- Cat
- Dog
cars:
- Volvo
- Skoda
V PHP by se stejná struktura zapsala jako:
[ // PHP
'pets' => [
'Cat',
'Dog',
],
'cars' => [
'Volvo',
'Skoda',
],
]
Lze kombinovat blokový a inline zápis:
pets: [Cat, Dog]
cars: [
Volvo,
Skoda,
]
Uvnitř inline zápisu již nelze používat zápis blokový, tohle nefunguje:
item: [
pets:
- Cat # TOHLE NELZE!!!
- Dog
]
V předchozím případě jsme zapsali mapování, jehož prvky byly sekvence, teď to zkusíme obráceně a vytvoříme
sekvenci obsahující mapování:
-
name: John
age: 35
-
name: Peter
age: 28
Není nutné, aby odrážky byly na samostatných řádcích, lze je umístit i tímto způsobem:
- name: John
age: 35
- name: Peter
age: 28
Je na vás, jestli klíče zarovnáte do sloupce pomocí mezer nebo použijete tabulátor.
Protože v PHP se používá pro mapování i sekvence stejná struktura, tedy pole, lze obojí sloučit. Odsazení je
tentokrát stejné:
- Cat
street: 742 Evergreen Terrace
- Goldfish
V PHP by se stejná struktura zapsala jako:
[ // PHP
'Cat',
'street' => '742 Evergreen Terrace',
'Goldfish',
]
Položka bez klíče dostane celočíselný klíč o jedna větší než největší celočíselný klíč před ní, stejně
jako v PHP. Takže {5: Cat, Dog} dá položce Dog klíč 6.
Řetězce
Řetězce v NEON lze uzavřít do jednoduchých i dvojitých uvozovek. Ale jak vidíte, mohou být také bez uvozovek.
- Řetězec v NEON bez uvozovek
- 'Řetězec v NEON v jednoduchých uvozovkách'
- "Řetězec v NEON ve dvojitých uvozovkách"
Pokud řetězec obsahuje znaky ` # " ' ` , : = - [ ] { } ( ) `, které lze zaměnit s NEON syntaxí, je potřeba
jej uzavřít do uvozovek. Doporučujeme použít jednoduché uvozovky, protože v nich se nepoužívá escapování. Pokud
potřebujete v takovém řetězci zapsat uvozovku, zdvojte ji:
'Uvozovka '' uvnitř řetězce v jednoduchých uvozovkách'
Dvojité uvozovky umožňují používat escape sekvence pro zápis speciálních znaků pomocí zpětných lomítek
\. Podporovány jsou všechny escape sekvence jako u formátu JSON a navíc \_, což je nedělitelná
mezera, tedy \u00A0.
- "\t \n \r \f \b \" \\ \/ \_"
- "\u00A9"
Existují další případy, kdy je potřeba uzavřít řetězce do uvozovek:
- začínají či končí mezerami
- vypadají jako čísla, booleany, nebo null
- NEON by je chápal jako datum
Víceřádkové řetězce
Víceřádkový řetězec začíná a končí trojitou uvozovkou na samostatných řádcích. Odsazení prvního neprázdného
řádku se odstraní ze všech řádků:
'''
první řádek
druhý řádek
třetí řádek
'''
V PHP bychom totéž napsali jako:
"první řádek\n\tdruhý řádek\ntřetí řádek" // PHP
Řádek odsazený méně než první neprázdný řádek si své odsazení ponechá celé. Řádek jen z mezer nebo
tabulátorů není prázdný, takže pokud je první, určí odsazení on.
Escapovací sekvence fungují jen u řetězců uvozených dvojitými uvozovkami místo apostrofů:
"""
Copyright \u00A9
"""
Zpětné lomítko na konci řádku ho nespojí s dalším řádkem, v řetězci zůstane.
Čísla
NEON rozumí číslům zapsaným v tzv. vědecké notaci a také číslům v binární, osmičkové a hexadecimální
soustavě:
- 12 # celé číslo
- 12.3 # float
- +1.2e-34 # exponenciální číslo
- 0b11010 # binární číslo
- 0o666 # osmičkové číslo
- 0x7A # hexa číslo
Předpony 0b, 0o a 0x se píšou malými písmeny a bez znaménka, takže
0X10 a -0x1 jsou řetězce. Úvodní nuly neznamenají osmičkové číslo: 0777 je
777. Podtržítka mezi číslicemi povolená nejsou, 1_000 je řetězec.
Nulls
Null lze v NEON vyjádřit pomocí null nebo neuvedením hodnoty. Povoleny jsou také varianty s velkým prvním
nebo velkými všemi písmeny.
a: null
b:
Booleans
Logické hodnoty jsou v NEON vyjádřeny pomocí true / false nebo yes /
no. Povoleny jsou také varianty s velkým prvním nebo velkými všemi písmeny.
[true, TRUE, True, false, yes, no]
Slova on a off, která YAML 1.1 čte jako logické hodnoty, jsou v NEONu
obyčejné řetězce.
Datum
NEON používá k vyjádření dat následující formáty a automaticky je převede na objekty
DateTimeImmutable:
- 2016-06-03 # datum
- 2016-06-03 19:00:00 # datum & čas
- 2016-06-03 19:00:00.1234 # datum & mikročas
- 2016-06-03 19:00:00 +0200 # datum & čas & zóna
- 2016-06-03 19:00:00 +02:00 # datum & čas & zóna
- 2016-06-03T19:00:00Z # ISO 8601 s T a zónou UTC
Literál, který vypadá jako datum, ale platným datem není, třeba 2024-02-30, se nepřevede a zůstane
řetězcem.
Entity
Entita je struktura, která připomíná volání funkce:
Column(type: int, nulls: yes)
V PHP se naparsuje jako objekt Nette\Neon\Entity:
// PHP
new Nette\Neon\Entity('Column', ['type' => 'int', 'nulls' => true])
Entity se mohou i zřetězit:
Column(type: int, nulls: yes) Field(id: 1)
Což se v PHP naparsuje tímto způsobem:
// 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]),
])
Hodnota Neon::Chain je !!chain, takže toto jméno je vyhrazené a pro vlastní entitu ho
použít nelze.
Uvnitř závorek platí pravidla pro inline zápis používaný u mapování a sekvencí, tedy může být klidně
i víceřádkový a pak není nutné uvádět čárky:
Column(
type: int
nulls: yes
)
Komentáře
Komentáře začínají znakem # a všechny následující znaky napravo jsou ignorovány:
# this line will be ignored by the interpreter
street: 742 Evergreen Terrace
city: Springfield # this is ignored too
country: USA
Neon versus JSON
JSON je téměř podmnožinou NEONu, takže prakticky každý JSON se dá parsovat jako NEON. Jedinou výjimkou je dvojtečka
na začátku řádku přilepená k hodnotě, třeba "a" a pod ním řádek s :1, což NEON čte jako
řetězec :1:
{
"php": {
"date.timezone": "Europe\/Prague",
"zlib.output_compression": true
},
"database": {
"driver": "mysql",
"username": "root",
"password": "beruska92"
},
"users": [
"Dave", "Kryten", "Rimmer"
]
}
Co kdybychom vynechali uvozovky?
{
php: {
date.timezone: Europe/Prague,
zlib.output_compression: true
},
database: {
driver: mysql,
username: root,
password: beruska92
},
users: [
Dave, Kryten, Rimmer
]
}
A složené závorky a čárky?
php:
date.timezone: Europe/Prague
zlib.output_compression: true
database:
driver: mysql
username: root
password: beruska92
users: [
Dave, Kryten, Rimmer
]
Nejsou seznamy s odrážkami lépe čitelné?
php:
date.timezone: Europe/Prague
zlib.output_compression: true
database:
driver: mysql
username: root
password: beruska92
users:
- Dave
- Kryten
- Rimmer
Přidáme komentáře?
# my web application config
php:
date.timezone: Europe/Prague
zlib.output_compression: true # use gzip
database:
driver: mysql
username: root
password: beruska92
users:
- Dave
- Kryten
- Rimmer
Hurá, teď znáte syntaxi NEONu!