Формат NEON

NEON – удобочитаемый формат структурированных данных. В Nette он используется для конфигурационных файлов. Он используется и для структурированных данных вроде настроек, языковых переводов и т. п. Попробуйте его в песочнице.

NEON расшифровывается как Nette Object Notation. Он менее сложный и громоздкий, чем XML или JSON, но даёт схожие возможности. Он очень похож на YAML. Главное преимущество в том, что у NEON есть так называемые сущности, благодаря которым конфигурация сервисов DI выглядит так соблазнительно. И он допускает табуляции для отступов.

NEON с самого начала создан так, чтобы им было легко пользоваться.

Интеграция

Синтаксис

Файл, написанный на NEON, обычно представляет собой последовательность или отображение.

Отображения

Отображение – набор пар ключ-значение; в PHP его назвали бы ассоциативным массивом. Каждая пара записывается как ключ: значение, пробел после : обязателен. Значением может быть что угодно: строка, число, логическое значение, null, последовательность или другое отображение.

street: 742 Evergreen Terrace
city: Springfield
country: USA

В PHP ту же структуру записали бы так:

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

Такая запись называется блочной, потому что все элементы находятся на отдельных строках и имеют одинаковый отступ (в данном случае никакого). NEON поддерживает для отображения и строчную запись, которая заключается в фигурные скобки, отступ никакой роли не играет, а разделителем элементов служит запятая или перевод строки:

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

То же самое, записанное на нескольких строках (отступ значения не имеет):

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

Как вариант, вместо : можно использовать =, и в блочной, и в строчной записи:

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

Последовательности

Последовательности – это индексированные массивы в PHP. Записываются они строками, начинающимися с дефиса -, за которым следует пробел. И снова значением может быть что угодно: строка, число, логическое значение, null, последовательность или другое отображение.

- Cat
- Dog
- Goldfish

В PHP ту же структуру записали бы так:

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

Такая запись называется блочной, потому что все элементы находятся на отдельных строках и имеют одинаковый отступ (в данном случае никакого). NEON поддерживает для последовательностей и строчную запись, которая заключается в квадратные скобки, отступ никакой роли не играет, а разделителем элементов служит запятая или перевод строки:

[Cat, Dog, Goldfish]

То же самое, записанное на нескольких строках (отступ значения не имеет):

[
	Cat, Dog
		Goldfish
]

В строчной записи дефисы (маркеры) использовать нельзя.

Сочетания

Значениями отображений и последовательностей могут быть другие отображения и последовательности. Главную роль играет уровень отступа. В следующем примере дефис, обозначающий элементы последовательности, имеет больший отступ, чем ключ pets, поэтому элементы становятся значением первой строки:

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

В PHP ту же структуру записали бы так:

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

Блочную и строчную запись можно сочетать:

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

Блочную запись нельзя использовать внутри строчной, вот так не получится:

item: [
	pets:
	 - Cat     # ТАК НЕЛЬЗЯ!!!
	 - Dog
]

В предыдущем случае мы записали отображение, элементами которого были последовательности. Теперь попробуем наоборот и создадим последовательность, содержащую отображения:

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

Дефисам не обязательно быть на отдельных строках, их можно поставить и так:

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

Выравнивать ли ключи в столбик пробелами или использовать символ табуляции – решать вам.

Поскольку PHP использует для отображений и последовательностей одну и ту же структуру (то есть массив), их можно объединять. Отступ на этот раз одинаковый:

- Cat
street: 742 Evergreen Terrace
- Goldfish

В PHP ту же структуру записали бы так:

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

Строки

Строки в NEON можно заключать в одинарные или двойные кавычки. Но, как видите, они могут быть и без кавычек.

- Строка в NEON без кавычек
- 'Строка в NEON в одинарных кавычках'
- "Строка в NEON в двойных кавычках"

Если строка содержит символы ` # " ' ` , : = - [ ] { } ( ) `, которые можно спутать с синтаксисом NEON, её нужно заключить в кавычки. Мы рекомендуем одинарные кавычки, потому что они не используют экранирование. Если вам нужно вставить в такую строку символ кавычки, удвойте его:

'Одинарная кавычка '' внутри строки в одинарных кавычках'

Двойные кавычки позволяют использовать escape-последовательности и записывать особые символы с помощью обратного слеша \. Поддерживаются все escape-последовательности формата JSON, а вдобавок \_, который обозначает неразрывный пробел, то есть \u00A0.

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

Есть и другие случаи, когда строки нужно заключать в кавычки:

  • они начинаются или заканчиваются пробелами
  • они выглядят как числа, логические значения или null
  • NEON истолковал бы их как даты

Многострочные строки

Многострочная строка начинается и заканчивается тройными кавычками на отдельных строках. Отступ первой строки игнорируется у всех строк:

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

В PHP то же самое мы бы записали так:

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

Escape-последовательности работают только для строк, заключённых в двойные кавычки, а не в апострофы:

"""
	Copyright \u00A9
"""

Числа

NEON понимает числа, записанные в научной нотации, а также числа в двоичной, восьмеричной и шестнадцатеричной системах:

- 12         # целое число
- 12.3       # дробное число
- +1.2e-34   # число в экспоненциальной записи

- 0b11010    # двоичное число
- 0o666      # восьмеричное число
- 0x7A       # шестнадцатеричное число

Значения null

Null в NEON можно выразить через null или опустив значение. Допускаются и варианты с прописной первой буквой или полностью прописными буквами (Null, NULL).

a: null
b:

Логические значения

Логические значения выражаются в NEON через true / false или yes / no. Допускаются и варианты с прописной первой буквой или полностью прописными буквами (True, TRUE, False, FALSE, Yes, YES, No, NO).

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

Даты

Для выражения дат NEON использует следующие форматы и автоматически преобразует их в объекты DateTimeImmutable:

- 2016-06-03                  # дата
- 2016-06-03 19:00:00         # дата и время
- 2016-06-03 19:00:00.1234    # дата и время с микросекундами
- 2016-06-03 19:00:00 +0200   # дата, время и часовой пояс
- 2016-06-03 19:00:00 +02:00  # дата, время и часовой пояс

Сущности

Сущность – структура, напоминающая вызов функции:

Column(type: int, nulls: yes)

В PHP она разбирается как объект Nette\Neon\Entity:

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

Сущности можно и объединять в цепочку:

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

Что в 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]),
])

Внутри скобок действуют правила строчной записи, используемой для отображений и последовательностей, так что она может быть многострочной, а запятые не обязательны:

Column(
	type: int
	nulls: yes
)

Комментарии

Комментарии начинаются с #, и все последующие символы справа игнорируются:

# эта строка будет проигнорирована интерпретатором
street: 742 Evergreen Terrace
city: Springfield  # это тоже игнорируется
country: USA

NEON против JSON

JSON – подмножество NEON. Поэтому любой JSON можно разобрать как NEON:

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

А что, если мы опустим кавычки?

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

А как насчёт фигурных скобок и запятых?

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

database:
	driver: mysql
	username: root
	password: password123

users: [
	Dave, Kryten, Rimmer
]

Не читаются ли списки с маркерами лучше?

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

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

Добавим комментарии?

# конфигурация моего веб-приложения

php:
	date.timezone: Europe/Prague
	zlib.output_compression: true  # используем gzip

database:
	driver: mysql
	username: root
	password: password123

users:
	- Dave
	- Kryten
	- Rimmer

Ура, теперь вы знаете синтаксис NEON!

версия: 3.x