Файл AppData\Local\Dropbox\info.json:
|
В новом формате выглядит так:
|
Конфигурационный файл редактора Sublime Text:
|
В новом формате выглядит так:
|
Немного истории
Данный формат обязан своим появлением другому формату со странным названием blockpar.
Blockpar разработал Алексей Дубовой (один из основателей Elemental Games) в процессе работы над игрой Космические рейнджеры. Впоследствии Александр Зеберг (бывший ведущий программист Katauri Interactive [после "распада" компании на Katauri Interactive и Elemental Games он ушёл в Katauri]) решил использовать данный формат для игры King's Bounty: Легенда о рыцаре.
Определение каждого игрового объекта хранилось в формате blockpar в отдельном файле с расширением .atom, например вот вырезка из файла data/data.kfs/spider.atom:
main {
class=chesspiece
model=spider.bma
cullcat=0
}
arena_params {
race=neutral
cost=24
level=1
leadership=14
attack=4
defense=4
...
resistances {
physical=20
poison=0
magic=0
fire=-10
}
...
}
...
Впоследствии [во время работы над проектом Royal Quest] я немного расширил этот формат, чтобы можно было вместо:
button {
name=close
pos=400,600
size=200,40
image=button_close.png
anchors=0,0,100,0
}
писать так:button=close,400,600,200,40 {
image=button_close.png
anchors=0,0,100,0
}
Также я добавил поддержку многострочных строковых значений посредством обратного апострофа (backtick — `):
button=... {
onmouseover=`
...
`
}
if len(indentation_levels) and indentation_levels[-1][0] == None: # сразу после символа `{` идёт новый произвольный отступ, который действует вплоть до парного символа `}`
И наконец в результате моего знакомства с Python-ом идея отказа от фигурных скобок настолько захватила меня, что я решил, что формат blockpar можно ещё больше упростить [отказавшись от обязательных фигурных скобок].
Также влияние на меня оказали:
- Текстовый формат хранения в Yet Another Serialization Library, использующейся в клиенте Royal Quest.
- Формат файла конфигурации nginx (впрочем, я отбросил идею отказаться от разделителя (символа
=
или:
) между именем параметра и его значением (почему)). - YAML (а именно идея использовать
.
перед именем элемента массива [в YAML используется-
]).
- Зачастую true/false используются в значении yes/no, on/off или enable/disable (например: you can enable show line endings; turn logging on/off; is digit? yes), а в булевой алгебре используются 0 и 1, так что использование ключевых слов true и false в большинстве случае довольно спорно.
- Мне не нравится истина/ложь в русской версии формата, а 0В и 1В (здесь В — русская заглавная в) можно связать с 0Выключено и 1Включено. [Вопрос о целесообразности русской версии прошу не поднимать.]
Строки в одиночных парных кавычках
Ещё один [помимо 0В и 1В] спорный/непривычный элемент данного формата — это использование парных кавычек
‘’
для сырых строк [без управляющих последовательностей \ escape sequences].Но мой выбор оправдывает тот факт, что Консорциум Юникода утвердил этот год — кодом открывающей одиночной парной кавычки.
Как такие кавычки набирать на клавиатуре — смотрите здесь.
Если в строке присутствуют непарные кавычки, тогда нужно выполнить "балансировку строки" аналогично тому, как это делается в пк-разметке для вставки HTML-кода.
Например есть строка
don’t
.Так как в ней присутствует несбалансированная закрывающая кавычка, добавим балансирующую открывающую кавычку в самое начало строки:
‘
don’t
.Сбалансированную строку заключаем в парные кавычки:
‘
‘don’t
’
.Теперь необходимо как-то показать парсеру, что добавленную слева кавычку не следует включать в строку, так как она нужна только для восстановления баланса. Для этого используется символ машинописного апострофа ', который нужно поставить по одной штуке на каждую балансирующую кавычку [таким образом, один машинописный апостроф "съедает" одну парную кавычку], в данном случае его необходимо поставить в начало строки:
'‘‘don’t’
.Сбалансированную строку можно как есть вставлять в другие строки в парных кавычках:
‘text = '‘‘don’t’’
.Использование
В данный момент есть реализация на Python и на JavaScript (можно попробовать cконвертировать JSON в новый формат прямо в браузере на веб-странице проекта).
Для Python — устанавливаем как обычно:
pip install thindf
Для JavaScript:
npm install thindf
node
const thindf = require('thindf');
И используем:
thindf.to_thindf(object, indent = 4)
для получения строки в формате thindf соответствующей переданному объекту (аналогjson.dumps
иJSON.stringify
).thindf.parse(str)
для получения объекта из строки в формате thindf (аналогjson.loads
иJSON.parse
).
[
{ "keys": ["f4"], "command": "f4" },
{ "keys": ["shift+f4"], "command": "f4", "args": {"shift_key_pressed": true} },
{ "keys": ["alt+shift+`"], "command": "insert", "args": {"characters": "`"} }, // (
{ "keys": [":", ")"], "command": "insert_snippet", "args": {"contents": ":)(:"} },
{ "keys": ["alt+9"], "context": [{"key": "selector", "operator": "equal", "operand": "text.pq"}], "command": "insert_pq" }, // ‘ (for balance)
{ "keys": ["alt+0"], "context": [{"key": "selector", "operator": "equal", "operand": "text.pq"}], "command": "insert", "args": {"characters": "’"} },
]
С использованием нового формата я бы записал так:f4 = on_f4()
shift+f4 = on_f4(shift_key_pressed' 1B)
alt+shift+` = insert(characters' ‘`’) // (
:,) = insert_snippet(contents' ‘:)(:’)
alt+9 = if selector == ‘text.pq’ {insert_pq()} else 0B // ‘ (for balance)
alt+0 = if selector == ‘text.pq’ {insert(characters' "’")} else 0B
Кусочек из файла d.json [из репозитория менеджера плагинов для Sublime Text]:
{
"schema_version": "3.0.0",
"packages": [
{
"name": "Django Lookup Snippets",
"details": "https://github.com/icycandle/sublime-django-lookup",
"releases": [
{
"sublime_text": "*",
"tags": true
}
]
},
{
"name": "Django Manage Commands",
"details": "https://github.com/vladimirnani/DjangoCommands",
"labels": ["Django", "python", "web", "management"],
"releases": [
{
"sublime_text": "<3000",
"tags": "st2-"
},
{
"sublime_text": ">=3000",
"tags": "st3-"
}
]
}
]
}
В новом формате выглядит так:schema_version = ‘3.0.0’
packages = [
. name = Django Lookup Snippets
details = https://github.com/icycandle/sublime-django-lookup
releases = [
. sublime_text = *
tags = 1B
]
. name = Django Manage Commands
details = https://github.com/vladimirnani/DjangoCommands
labels = [
Django
python
web
management
]
releases = [
. sublime_text = <3000
tags = st2-
. sublime_text = >=3000
tags = st3-
]
]
Some corner cases: | |
|
|
Комментарии (72)
qnok
06.08.2018 10:12+2А можно ещё добавить в статью табличку преимуществ и недостатков по сравнению с json.
Из преимуществ вроде как большая компактность.
Из недостатков — гораздо меньшая распространенность, а чтобы победить этот недостаток преимущества должны быть действительно очень значительными. Кавычки и фигурные скобки, как-то не тянут на это.
maxzh83
06.08.2018 10:20+2В json можно в одну строчку:
{ "personal": { "host": 5060852864, "is_team": false}}
В thindf так можно? В статье не увидел примера.alextretyak Автор
06.08.2018 10:34В текущей реализации, увы, нельзя.
Вы [или возможно кто-нибудь другой {хороший пример в любом случае пригодится}] не могли бы привести пример реально использующегося где-либо json файла, в котором такая запись будет лучше, чем:
?personal host = 5060852864 is_team = 0B
(Предполагаю, должно быть много таких элементов.)maxzh83
06.08.2018 10:39+2В таком формате передаются данные там, где их не надо читать человеком, например клиенту с сервера. Такой формат выбран просто потому, что он занимает меньше места из-за отсутствия пробелов и табуляций. А для человеческих конфигов есть YAML
alextretyak Автор
06.08.2018 10:46Хм, а вы сами используете YAML?
ИМХО, это слишком переусложнённый формат.
Поэтому для конфигов чаще используют JSON и даже XML.maxzh83
06.08.2018 10:58+1Да, использую, и он местами похож на предложенный в статье.
и даже XML.
И это ужасно. Его придумали для машинного обмена и там он еще более-менее уместен, но людям его давать негуманно. К счастью, он начал потихоньку исчезать.
lair
06.08.2018 11:28Поэтому для конфигов чаще используют JSON
Правда? То-то у AppVeyor и GitVersion конфиги в yml.
и даже XML.
… это XML-то проще, чем YAML?
VolCh
06.08.2018 13:13Очень часто в YAML-файлах используется лишь небольшое надмножество JSON, такие фичи как:
- нет необходимости простые ключи и строковые значения в кавычки заключать
- нет необходимости ставить [] и {} в многострочных объявлениях, вместо них отступы (в случае [] с '-' после отступа)
- комментарии
То есть в таком режиме YAML даже проще JSON пишется и читается в общем случае, хотя бывают иногда неоднозначности, обычно при модификации конфига и забывание про добавление кавычек.
lair
06.08.2018 11:30Вы не могли бы привести пример реально использующегося где-либо json файла
Основное применение JSON — вовсе не "файлы". А в API и БД, и вообще везде, где не нужно чтение человеком, ровно так и пишут, ибо незачем.
alextretyak Автор
06.08.2018 11:45Давайте не будем голословны.
Примеры в статье вполне реальны и именно на такое standalone применение и ориентирован новый формат в первую очередь. Но улучшение читаемости не повредит и в применении для всяких API.
А там где
не нужно чтение человеком
лучше подойдёт BSON или Protocol Buffers.lair
06.08.2018 11:48+2Примеры в статье вполне реальны и именно на такое standalone применение и ориентирован новый формат в первую очередь.
Если "такое применение" — это конфиги, то сравнивайте с форматами для конфиг-файлов. Можно начать с YAML и HOCON.
Но улучшение читаемости не повредит и в применении для всяких API.
Именно этим JSON прекрасен — можно передавать поток без лишних символов, а потом отформатировать этот поток в читаемый вид во время отображения.
лучше подойдёт BSON или Protocol Buffers.
… у которых нет встроенной поддержки в браузерах, ага.
borislav
06.08.2018 10:25-1Кто-то думает что формат стал более читабелен? Если нет, то какая разница как там передаются данные, все равно json чаще всего формируют библиотеками а не пишут руками. Да и руками его написать проще, чем вдумываясь куда нужно поставить обратный апостроф (кстати где он на клавиатуре?) и считая количество пробелов.
Busla
06.08.2018 10:31Каким местом это альтернатива JSON, если в браузеры ничего другого толком не завезли?!
Выбор в пользу JSON в некоторых продуктах не очевиден, но такие примеры можно для любого формата подыскать. Для конфигов больше предназначен YAML — почему не с ним сравниваете? Чем thindf лучше?alextretyak Автор
06.08.2018 10:41Ну JSON используется не только в вебе, но и, к примеру, для файлов конфигурации. Именно для таких применений данный формат и создавался в первую очередь.
trapwalker
06.08.2018 12:49Давайте я попробую угадать «правильный» ответ=).
У YAML по сравнению с thindf есть два недостатка: первый — это некоторая «излишняя переусложнённость», а второй недостаток фатальный.=)
Вообще я открывал эту статью с мыслью, что уж теперь-то, запостив такую статью на хабр, автор, наверно, прикрыл все слабые места и придумал ответы на все каверзные вопросы про сравнение с yaml, про распространённость, про самопальность, про модифицируемость, про скорость… Но нет.
К сожалению нет.
Как бы ни был бесполезен очередной велосипед, если этот велосипед продуман и сделан хорошо, если он не лишен изящества и не блещет квадратными колёсами, то это уже интересно. Просто как ход мыслей или ход инженерной разработки.
Я ожидал в этой статье увидеть сравнительные замеры скорости парсинга, сравнения в эффективности представления тех или иных конструкций (не только с одним json, но и с прочими конкурентами),eirnym
06.08.2018 15:07В данном случае колёса треугольные и неравнобедренные, вспоминая русское В в булевых значениях.
trapwalker
07.08.2018 15:39Да там не русская буква, это так автор обосновал выбор, что, мол, на обоих языках мнемонически получается.
alextretyak Автор
07.08.2018 15:50Почему не русская?
В 0В и 1В допускается использовать как английскую, так и русскую В.
eirnym
07.08.2018 16:23а 0В и 1В (здесь В — русская заглавная в) можно связать с 0Выключено и 1Включено.
хотя я код не читал, чтобы утверждать наверняка
trapwalker
07.08.2018 15:42Кстати, о колёсах. Это ж надо было нормальные пакеты подготовить для основных языков, покрыть тестами код, замеры производительности те же самые.
Ещё большое беспокойство вызывает экранирование. Надо, конечно, разбираться и погружаться, но во всяких настройках часто урлы, айпи-адреса, пути встерчаются, всякие уникодные штуки… как с ними этот формат себя поведёт, как синтаксис устоит…
Непростое это дело — новые форматы изобретать.
Griboks
06.08.2018 12:09Отличная идея, но есть один фатальный недостаток: многократное увеличение размера. Может быть, для трех уровней отступы лучше (вы убирает пару лишних знаков). Но вот для десяти — хуже(вы заменяет пару знаков на десятки лишних табуляций).
Я так понимаю, что этот формат ориентирован на программиста. Поэтому предлагаю написать транслятор в json.alextretyak Автор
06.08.2018 12:20-1Отличная идея, но есть один фатальный недостаток: многократное увеличение размера.
Недостаток при сравнении с чем? В человекочитаемых конфигах на JSON используются также отступы в 4 пробела на один уровень.
предлагаю написать транслятор в json.
Это уже возможно в рамках текущей реализации.
Python:
JavaScript:string_in_json = json.dumps(thindf.parse(string_in_thindf))
string_in_json = JSON.stringify(thindf.parse(string_in_thindf));
dmitry_dvm
06.08.2018 12:20+1А чем жсон-то не угодил?
В этот формат комментарии тоже не завезли?
Вопрос о целесообразности русской версии прошу не поднимать
И все же?alextretyak Автор
06.08.2018 13:02А чем жсон-то не угодил?
При правке различных конфигов периодически забываю ставить запятые. А также не нравится обязательное заключение параметров и их значения в кавычки.
В этот формат комментарии тоже не завезли?
Хотя явной поддержки комментариев в данной реализации нет, но особенность этого формата такова, что строка:
не является ошибкой, а является по смыслу аналогичной вот такой строки в JSON://font_face = Fira Code
"//font_face": "Fira Code"
При таком подходе "комментарии" сохраняются автоматически, а не удаляются как происходит к примеру в JSON-парсерах с поддержкой комментариев.
И все же?
Не понял ваш вопрос. Русская версия поддерживается и всё, в чём она заключается, это поддержка русской буквыВ
в0В
и1В
, а также русскаяН
в значенииnull
/None
.eirnym
06.08.2018 15:10"сделаем так, чтобы китайцы (подставить любую группу людей по вкусу) не могли редактировать наши конфиги"
trapwalker
07.08.2018 15:57периодически забываю ставить запятые. А также не нравится обязательное заключение параметров и их значения в кавычки
Да это, прям. антипаттерн какой-то для мотивации создания нового формата.
Эдак если кто ошибается в «ться/тся» постоянно, то можно правила подкорректировать,
Прелесть обязательных кавычек в том, что эти правила останутся неизменными если в ключе у вас встретится "=" по какой-то причине.
Кстати, на счет комментарием в данных — это интересный подход.
Беда форматов типа json с комментариями в том, что при программной обработке и пересериализации данных эти комментарии, как вариативное форматирование исчезают. И не понятно как их вернуть или разместить при программной генерации файла.
Особый формат ключа, конечно, тот ещё способ по универсальности… но занести комментарии или, если смотреть шире, докстринги, прямо в синтаксис — это идея интересная, как мне кажется.
Geckelberryfinn
06.08.2018 13:04чтобы можно было вместо:
button {
name=close
pos=400,600
size=200,40
image=button_close.png
anchors=0,0,100,0
}
писать так:
button=close,400,600,200,40 {
image=button_close.png
anchors=0,0,100,0
}
Сомнительное достижение, на мой взгляд. Во-первых, во втором примере абсолютно не ясно без исходного кода программы, что из себя представляют числа 400, 600, 20, 40, а во-вторых, каким образом тогда можно извлечь все элементы, у которых, например, name начинается с «close*»? Для json хотя бы можно использовать JOLT . И в-третьих, в некоторых приложениях все-таки желательно сочетать метаданные с данными, ибо json все-таки не только в Web используется
ZaEzzz
06.08.2018 13:21Мне кажется, вы нашли фатальный недостаток в JSON.
Ещё один [помимо 0В и 1В] спорный/непривычный элемент данного формата — это использование парных кавычек ‘’ для сырых строк [без управляющих последовательностей \ escape sequences].
Вот меня это неистово смущает — должен быть только один способ, иначе это усложнение и будут ошибки.
Да и по самому формату данных тоже как-то все теряется, сложно читается и неоднозначно интерпретируется.
FeNUMe
06.08.2018 13:34Во-первых как уже сказали вы изобрели конкурента для YAML/INI, а не JSON.
Во-вторых «0В и 1В» это изврат ухудшающий читабельность, для человеческих конфигов true/false самый оптимальный вариант.trapwalker
07.08.2018 16:00Вы, сударь, похоже не в курсе обо всех возможностях ямла, раз так говорите. Одни внутренние ссылки и расширяемость чего стоят.
VolCh
07.08.2018 19:15С другой стороны, увидев что-то подобное в yaml разработчик может решить отказаться от его использования в пользу того же json.
eirnym
06.08.2018 14:58Сколько байт выигрывает приведённый формат по сравнению с JSON? я предполагаю, что это не более 10-15% в худшем случае, в лучшем около 5%.
PS: прошу прощение, отступы съедят все преимущества в этом плане. то есть, в том "лучшем" случае будет -10 --15%
rraderio
06.08.2018 15:32Можно пример со списком обьектов?
[{"name": "Nexus"}, {"name": "Pixel"}]
alextretyak Автор
07.08.2018 04:17-1[ . name = Nexus . name = Pixel ]
ZaEzzz
07.08.2018 08:59Ну… Судя по вашим примера, это вот это…
[{"name": "Nexus","name": "Pixel"}]
alextretyak Автор
07.08.2018 09:02Вы привели невалидный JSON. Вообще, я уже упоминал в статье — можно попробовать cконвертировать JSON в новый формат прямо в браузере на веб-странице проекта.
ZaEzzz
07.08.2018 11:47Конечно невалидный. Я в подобных конвертациях ожидаю, что оно однозначно и просто конвертируется в обе стороны…
И тут до меня дошло, что там еще и точки есть… Ну, знаете… Перебор по подводным камням.
rraderio
07.08.2018 10:37[{"name": "Nexus", "lol": 42}, {},{"name": "Pixel"}]
Конвертор thindf
[ . name = Nexus lol = 42 . {} . name = Pixel ]
Это нормально?alextretyak Автор
07.08.2018 12:04Ну да. Точка является обозначением начала нового подобъекта в массиве (аналогично в YAML используется "
-
": можете сами попробовать конвертер JSON в YAML).
А какую бы вы запись предпочли?rraderio
07.08.2018 12:29Я бы хотел больше консистентности, а не в одном месте обьект это точка, в другом {}.
YuryB
06.08.2018 21:50основное преимущество json не в читаемости или просто внешнем виде (что пытаются улучшить «изобретатели»), а в том что он совместим с js и легко и не принуждённо встраивается в его тело, а так же напрямую пишется-читается. В каком-то смысле json это js в котором хранятся только данные. Так что эта и остальные библиотеки напирают на какие-то второстепенные моменты, из-за улучшения которых никто не перестанет использовать json
An70ni
07.08.2018 04:19а что насчет вложенных объектов?
alextretyak Автор
07.08.2018 04:20thindf поддерживает практически всё, что поддерживает JSON.
adictive_max
07.08.2018 06:07Практически? JSON сам по себе довольно дубовый, а thindf даже из этого не всё может?
An70ni
07.08.2018 07:40мне просто интересно как это будет выглядеть? граница между вложенным и родительским объектом определяется по количеству отступов?
alextretyak Автор
07.08.2018 08:14Можете привести пример на JSON? Я не очень понимаю, что вы имеете в виду.
anonymous
08.08.2018 01:49Похоже на делфийский DFM.
Кстати, в Delphi _очень_ быстрая загрузка из DFM-файлов.
vintage
08.08.2018 08:39-1Думаю вам будет небезынтересно глянуть на более продуманный формат: https://habr.com/post/248147/
alextretyak Автор
08.08.2018 13:14Да, я уже видел вашу статью. Но, если честно, не очень впечатлили возможности этого формата (нет комменатриев и массивов [а это и правда удобно, когда формат данных гладко ложится на структуры данных используемого языка программирования (или вы при решении задач никогда не пользовались массивами?), и в этом я вижу основную причину такой популярности JSON]).
У вас в статье заявлена реализация на TypeScript/JavaScript, но я её не нашёл.
И с примерами вы "читерите":
Примеры файлов на разных языках: github.com/nin-jin/tree.d/tree/master/formats
Берём sample.json:
Сразу мне стало интересно как этот пример, использующий массив users, ляжет на ваш формат, который массивы не поддерживает.{ "users" : [ { "name" : "John", "age" : 30 }, { "name" : "John", "age" : 30 }...
В sample.tree видим:
user name \John age 30 user name \John age 30
Ещё интереснее. Как получили строкиuser
? Неужели конвертер настолько умный, что догадался откусить признак множественного числа — последнюю букву 's' в слове users?
Оказалось, ничего подобного.
Вот результат честной конвертации:
ideone.com/9rlHxi:
dict * \users : list dict * \name : string \John * \age : int \30 dict * \name : string \John * \age : int \30
И вы поставили человекопонятность этому формату пятёрку?
P.S. Для ленивых вот результат конвертации sample.json в YAML и thindf:YAML: thindf: --- users: users = [ - name: John . name = John age: 30 age = 30 - name: John . name = John age: 30 age = 30 ... ... ]
vintage
08.08.2018 15:29Реализация на TS: https://github.com/eigenmethod/mol/tree/master/tree
Смотрите, есть XML — это формат, в нём нет никаких заголовков, параграфов, кругов и прочего. А есть производные от него языки: XHTML, SVG, RDF и прочие, где есть куча идиом, небходимых для соответствующих предметных областей. Так вот, tree — это максимально абстрактный формат, где нет ничего кроме иерархии абстрактных узлов (AST). На его основе вы вольны разрабатывать произвольные языки: dom.tree для представления dom дерева, где нода с именем
--
обозначает комментарий; view.tree для описания компонент, где-
обозначает комментарий; grammar.tree, гдеremark
обозначает комментарий и так далее. Можете рассматривать формат, как некоторый фреймворк для создания DSL.
В упомянутом
view.tree
есть и массивы, и словари, и прочие идиомы JSON, если они вам нужны. Ваш пример будет выглядеть, например, так:
users / * name \John age 30 * name \John age 30
Это именованный список с нетипизированными словарями внутри, который однозначно преобразуется в JSON.
Однако, важно понимать, в других языках может быть удобным совершенно иное представление. Например, более гибкий и наглядный неименованный список с типизированными узлами:
user name \John age 30 user name \John age 30
В JSON подобное можно представить лишь через костыли:
[ [ "user" , { "name" : "John", "age" : 30 } ], [ "user" , { "name" : "John", "age" : 30 } ] ]
[ { "@type" : "user", "name" : "John", "age" : 30 }, { "@type" : "user", "name" : "John", "age" : 30 } ]
И наоборот, если в словарях в tree нужна поддержка переводов строк внутри ключей (довольно редкий кейс), то представление полностью совместимое с моделью JSON будет немного костыльным:
* \users : / * \name : \John \age : 30 * \name : \John \age : 30
Тот код, что вы привели думаю стоит переработать. Он делает из JSON какую-то переусложнённую tree структуру.
iShatokhin
08.08.2018 20:50Ой, кажется, я его сломал.
{ "bool": [[{}]] } // v.slice is not a function
Что-то с большой вложенностью пустых массивов также проблема.
{ "bool": [[[[]]]] } /* bool = [ [‘’] ] */ { "bool": [[[[[[[]]]]]]] } /* bool = [ [‘’] ] */
ZaEzzz
09.08.2018 08:44Там во вложенности можно и дальше ирать с эффектами
{ "var": [[[{}]]] } { "var": [[[{"qwe":"qwe"}]]] } /* var = [ [[object Object]] ] */ { "var": [[[{"qwe":"qwe"},[]]]]} /* А теперь это строка var = [ [‘[object Object],’] ] */ { "var": [[[{},"0B", true]]]} /* Добавим немного рокировки типов... var = [ [[object Object],0B,true] ] */ { "var": [[["0B", true, 123]]]} /* var = [ [‘0B,true,123’] ] */
Punk_Joker
INI на стероидах?
qnok
— удалено, не та ветка -