
Усложнённый упрощённый JSON
Есть такой известный и весьма простой текстовый формат JSON.
JSON формат определяет следующие типы: null, boolean (true, false), number, string, array, object.
А что, если поставить задачу о представлении любых JSON данных с помощью всего 4 типов: number, string, array, object?

Добро пожаловать в ненормальное программирование!
Гость программы: NSNJSON (Not So Normal JSON)!
Термины и обозначения
Представления для «простых» типов
Представления для «контейнерных» типов
Восстановление JSON
Восстановление JSON для «простых» типов
Восстановление JSON для «контейнерных» типов
Примеры
Драйверы
Заключение
Попробуем подойти к данной задаче немного формально. В этой статье я буду использовать обозначения взятые с сайта json.org. И для удобства добавлю немного своих.
Введем тип boolean = true | false.
А еще введем тип name, значения которого состовляют подмножество значений типа string — те значения, которые являются корректным именем для поля объекта.
В NSNJSON представлениях используется всего три поля:
К «простым» типам будем относить следующие: null, boolean, string, number.
Определим NSNJSON представление Pnull : null → object
Определим NSNJSON представление Ptrue : true → object
Определим NSNJSON представление Pfalse : false → object
Определим NSNJSON представление Pstring : string → object
Определим NSNJSON представление Pnumber : number → object
Определим NSNJSON представление Psimple : «простой» тип → object:
Psimple(value) = Pnull(value), если value значение типа null,
Psimple(value) = Ptrue(value), если value значение типа true,
Psimple(value) = Pfalse(value), если value значение типа false,
Psimple(value) = Pstring(value), если value значение типа string,
Psimple(value) = Pnumber(value), если value значение типа number.
К «контейнерным» типам будем относить следующие: array, object.
И array и object содержат элементы, поэтому необходимо:
Сперва рассмотрим «контейнеры», значения в которых имеют только «простой» тип.
Для начала разберемся с массивами, то есть значениями типа array.
Пусть массив data это значение типа array, тогда можно представить массив следующим образом:
data = (e1, ..., en),
где для всех i = 1, ..., n,
n — длина массива,
ei — элемент массива — значение «простого» типа.
Применим функцию представления Psimple к каждому элементу массива data.
dataElementsPresentation = (Psimple(e1), ..., Psimple(en)).
Определим NSNJSON представление Parray : array → object
Теперь разберемся с объектами, то есть значениями типа object.
Пусть объект data это значение типа object, тогда можно представить объект следующим образом:
data = { (name1, value1), ..., (namen, valuen) },
где для всех i = 1, ..., n,
n — количество полей объекта,
(namei, valuei) — поле объекта,
namei — имя поля
valuei — значение поля — значение «простого» типа.
В JSON спецификации сказано, что объект это неупорядоченный набор полей, однако в каждом конкретном случае, мы всегда можем перебрать все поля объекта и пронумеровать их в порядке перебора. Воспользовавшись таким приемом, монжно представить объект data в качестве массива полей без потери общности.
Пусть valuePresentation — результат применения функции представления Psimple к значению value.
Определим NSNJSON представление Pfield : name × value → object
Применим функцию представления Pfield к каждому поля объекта data.
dataFieldsPresentation = (Pfield(name1, value1), ..., Pfield(namen, valuen)).
Определим NSNJSON представление Pobject : object → object
Определим NSNJSON представление Pcontainer : «контейнерный» тип → object:
Pcontainer(value) = Parray(value), если value значение типа array,
Pcontainer(value) = Pobject(value), если value значение типа object.
Наконец, определим итоговое NSNJSON представление Pjson : json → object:
Pjson(value) = Psimple(value), если value значение «простого» типа,
Pjson(value) = Pcontainer(value), если value значение «контейнерного» типа.
Если теперь в алгоритмах представления для «контейнерных» типов вместо функции Psimple использовать функцию Pjson, то получим функции представления, которые могут работать с «контейнерами», содержащими любые JSON значения.
Таким образом была построена схема представления любых корректных JSON данных с помощью всего четырех JSON типов: number, string, array, object.
У нас есть JSON, мы из него теперь можем получить NSNSJON.
Но можно ли теперь восстановить исходный JSON?
Можно.
Определим функцию получения типа JSON значения Ptype : object → string
Пусть type — результат применения функции Ptype к представлению presentation.
Определим функцию восстановления Rnull : object → null
Определим функцию восстановления Rnumber : object → string
Определим функцию восстановления Rnumber : object → number
Определим функцию восстановления Rboolean : object → boolean
Определим функцию восстановления Rsimple : object → «простой» тип
Rsimple(presentation) = Rnull(presentation), если type = «null»,
Rsimple(presentation) = Rstring(presentation), если type = «string»,
Rsimple(presentation) = Rnumber(presentation), если type = «number».
Rsimple(presentation) = Rboolean(presentation), если type = «boolean»,
Также как и ранее, сперва рассмотрим «контейнеры», значения в которых имеют только «простой» тип.
Пусть имеется представление presentation массива data.
Применим функцию восстановления Rsimple к каждому элементу массива presentation.v.
data = (e1, ..., en),
где для всех i = 1, ..., n,
ei — Rsimple(presentation.v[i]) — элемент массива.
Определим функцию восстановления Rarray : object → array
Пусть теперь имеется представление presentation объекта data.
Применим функцию восстановления Rsimple к каждому элементу массива presentation.v и используя значение поля n восстановим поля объекта.
data = (e1, ..., en),
где для всех i = 1, ..., n,
ei — (namei, valuei) — поле объекта,
namei — presentation.v[i].n — имя поля
valuei — Rsimple(presentation.v[i]) — значение поля.
Определим функцию восстановления Robject : object → object
Определим функцию восстановления Rcontainer : object → «контейнерный» тип
Rcontainer(presentation) = Rarray(value), если type = «array»,
Rcontainer(presentation) = Robject(value), если type = «object».
И в итоге, определим функцию восстановления Rjson : object → json:
Rjson(presentation) = Rsimple(presentation), если восстанавливается значение «простого» типа,
Rjson(presentation) = Rcontainer(presentation), если восстанавливается значение «контейнерного» типа.
Если теперь в алгоритмах восстановления для «контейнерных» типов вместо функции Rsimple использовать функцию Rjson, то получим функции представления, которые могут работать с «контейнерами», содержащими любые JSON значения.
В заключении, хотелось бы показать несколько простых примеров демонстрирующих применение формата NSNJSON.
Я сделал два небольших драйвера для желающих поиграться с данным форматом.
Драйверы доступны на GitHub на странице проекта: nsnjson!
Драйверы:
Хорошая новость для любителей npmjs.com!
Теперь Node.js драйвер доступен и там!
А если Вы хотите попробовать NSNJSON с помощью Java драйвера, то на странице проекта Вы сможете найти инструкцию как настроить Maven файлик pom.xml, чтобы не скачивать драйвер вручную! :)
Мне осталось напомнить, что сегодня гостем программы «Ненормальное программирование» был NSNJSON (Not So Normal JSON)!
Спасибо за внимание!
JSON формат определяет следующие типы: null, boolean (true, false), number, string, array, object.
А что, если поставить задачу о представлении любых JSON данных с помощью всего 4 типов: number, string, array, object?

Добро пожаловать в ненормальное программирование!
Гость программы: NSNJSON (Not So Normal JSON)!
Содержание
Термины и обозначения
Представления для «простых» типов
Представления для «контейнерных» типов
Восстановление JSON
Восстановление JSON для «простых» типов
Восстановление JSON для «контейнерных» типов
Примеры
Драйверы
Заключение
Попробуем подойти к данной задаче немного формально. В этой статье я буду использовать обозначения взятые с сайта json.org. И для удобства добавлю немного своих.
Термины и обозначения
Введем тип boolean = true | false.
А еще введем тип name, значения которого состовляют подмножество значений типа string — те значения, которые являются корректным именем для поля объекта.
В NSNJSON представлениях используется всего три поля:
- t — type — тип значения (обязательное поле),
- v — value — значение (обязательное поле),
- n — name — имя поля (используется в представлениях полей объекта).
Представления для «простых» типов
К «простым» типам будем относить следующие: null, boolean, string, number.
Определим NSNJSON представление Pnull : null → object
value -> { "t": "null" }
Определим NSNJSON представление Ptrue : true → object
value -> { "t": "boolean", "v": 1 }
Определим NSNJSON представление Pfalse : false → object
value -> { "t": "boolean", "v": 0 }
Определим NSNJSON представление Pstring : string → object
value -> { "t": "string", "v": value }
Определим NSNJSON представление Pnumber : number → object
value -> { "t": "number", "v": value }
Определим NSNJSON представление Psimple : «простой» тип → object:
Psimple(value) = Pnull(value), если value значение типа null,
Psimple(value) = Ptrue(value), если value значение типа true,
Psimple(value) = Pfalse(value), если value значение типа false,
Psimple(value) = Pstring(value), если value значение типа string,
Psimple(value) = Pnumber(value), если value значение типа number.
Представления для «контейнерных» типов
К «контейнерным» типам будем относить следующие: array, object.
И array и object содержат элементы, поэтому необходимо:
- во-первых, определить представление для каждого элемента,
- во-вторых, определить итоговое представление всего «контейнера», на основе представлений его элементов.
Сперва рассмотрим «контейнеры», значения в которых имеют только «простой» тип.
Для начала разберемся с массивами, то есть значениями типа array.
Пусть массив data это значение типа array, тогда можно представить массив следующим образом:
data = (e1, ..., en),
где для всех i = 1, ..., n,
n — длина массива,
ei — элемент массива — значение «простого» типа.
Применим функцию представления Psimple к каждому элементу массива data.
dataElementsPresentation = (Psimple(e1), ..., Psimple(en)).
Определим NSNJSON представление Parray : array → object
data -> { "t": "array", "v": dataElementsPresentation }
Теперь разберемся с объектами, то есть значениями типа object.
Пусть объект data это значение типа object, тогда можно представить объект следующим образом:
data = { (name1, value1), ..., (namen, valuen) },
где для всех i = 1, ..., n,
n — количество полей объекта,
(namei, valuei) — поле объекта,
namei — имя поля
valuei — значение поля — значение «простого» типа.
В JSON спецификации сказано, что объект это неупорядоченный набор полей, однако в каждом конкретном случае, мы всегда можем перебрать все поля объекта и пронумеровать их в порядке перебора. Воспользовавшись таким приемом, монжно представить объект data в качестве массива полей без потери общности.
Пусть valuePresentation — результат применения функции представления Psimple к значению value.
Определим NSNJSON представление Pfield : name × value → object
(name, value) -> { "n": name, "t": valuePresentation.t, "v": valuePresentation.v }
Применим функцию представления Pfield к каждому поля объекта data.
dataFieldsPresentation = (Pfield(name1, value1), ..., Pfield(namen, valuen)).
Определим NSNJSON представление Pobject : object → object
data -> { "t": "object", "v": dataElementsPresentation }
Определим NSNJSON представление Pcontainer : «контейнерный» тип → object:
Pcontainer(value) = Parray(value), если value значение типа array,
Pcontainer(value) = Pobject(value), если value значение типа object.
Наконец, определим итоговое NSNJSON представление Pjson : json → object:
Pjson(value) = Psimple(value), если value значение «простого» типа,
Pjson(value) = Pcontainer(value), если value значение «контейнерного» типа.
Если теперь в алгоритмах представления для «контейнерных» типов вместо функции Psimple использовать функцию Pjson, то получим функции представления, которые могут работать с «контейнерами», содержащими любые JSON значения.
Таким образом была построена схема представления любых корректных JSON данных с помощью всего четырех JSON типов: number, string, array, object.
Восстановление JSON
У нас есть JSON, мы из него теперь можем получить NSNSJON.
Но можно ли теперь восстановить исходный JSON?
Можно.
Определим функцию получения типа JSON значения Ptype : object → string
presentation -> presentation.t
Пусть type — результат применения функции Ptype к представлению presentation.
Восстановление JSON для «простых» типов
Определим функцию восстановления Rnull : object → null
presentation -> if (type == "null") { return null; }
Определим функцию восстановления Rnumber : object → string
presentation -> if (type == "string") { return presentation.v; }
Определим функцию восстановления Rnumber : object → number
presentation -> if (type == "number") { return presentation.v; }
Определим функцию восстановления Rboolean : object → boolean
presentation -> if (type == "boolean") { return presentation.v != 0; }
Определим функцию восстановления Rsimple : object → «простой» тип
Rsimple(presentation) = Rnull(presentation), если type = «null»,
Rsimple(presentation) = Rstring(presentation), если type = «string»,
Rsimple(presentation) = Rnumber(presentation), если type = «number».
Rsimple(presentation) = Rboolean(presentation), если type = «boolean»,
Восстановление JSON для «контейнерных» типов
Также как и ранее, сперва рассмотрим «контейнеры», значения в которых имеют только «простой» тип.
Пусть имеется представление presentation массива data.
Применим функцию восстановления Rsimple к каждому элементу массива presentation.v.
data = (e1, ..., en),
где для всех i = 1, ..., n,
ei — Rsimple(presentation.v[i]) — элемент массива.
Определим функцию восстановления Rarray : object → array
presentation -> if (type == "array") { return data; }
Пусть теперь имеется представление presentation объекта data.
Применим функцию восстановления Rsimple к каждому элементу массива presentation.v и используя значение поля n восстановим поля объекта.
data = (e1, ..., en),
где для всех i = 1, ..., n,
ei — (namei, valuei) — поле объекта,
namei — presentation.v[i].n — имя поля
valuei — Rsimple(presentation.v[i]) — значение поля.
Определим функцию восстановления Robject : object → object
presentation -> if (type == "object") { return data; }
Определим функцию восстановления Rcontainer : object → «контейнерный» тип
Rcontainer(presentation) = Rarray(value), если type = «array»,
Rcontainer(presentation) = Robject(value), если type = «object».
И в итоге, определим функцию восстановления Rjson : object → json:
Rjson(presentation) = Rsimple(presentation), если восстанавливается значение «простого» типа,
Rjson(presentation) = Rcontainer(presentation), если восстанавливается значение «контейнерного» типа.
Если теперь в алгоритмах восстановления для «контейнерных» типов вместо функции Rsimple использовать функцию Rjson, то получим функции представления, которые могут работать с «контейнерами», содержащими любые JSON значения.
Примеры
В заключении, хотелось бы показать несколько простых примеров демонстрирующих применение формата NSNJSON.
примерчики
JSON | NSNJSON (Not So Normal JSON) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Драйверы
Я сделал два небольших драйвера для желающих поиграться с данным форматом.
Драйверы доступны на GitHub на странице проекта: nsnjson!
Драйверы:
Хорошая новость для любителей npmjs.com!
Теперь Node.js драйвер доступен и там!
А если Вы хотите попробовать NSNJSON с помощью Java драйвера, то на странице проекта Вы сможете найти инструкцию как настроить Maven файлик pom.xml, чтобы не скачивать драйвер вручную! :)
Заключение
Мне осталось напомнить, что сегодня гостем программы «Ненормальное программирование» был NSNJSON (Not So Normal JSON)!
Спасибо за внимание!
Comments 21
Only users with full accounts can post comments. Log in, please.