CSHARP_GEPARD Telegram 155
JsonPath в .NET #решение

Представим себе, что есть сервис, который умеет получать данные из Kafka и складывать полученные данные в БД. Без программирования, просто декларативным указанием topic и таблицы в БД. То есть:

1. Сервис работает по запросу (job или unit-of-work).
2. При создании job описывается маппинг данных из Kafka в нужную таблицу.
3. Описывается фильтрация и преобразовывает данных из Kafka так, как пользователю удобно. Ну чтобы не заниматься этим при каждом запросе в БД.

То есть, во-первых, нужен вменяемый API, которым удобно пользоваться. Во-вторых, нужно описание маппинга полей сообщения из Kafka в поля Data-base-object (DBO). Ну и всякая фильтрация (например, отсечение удалённых), выбор определённых полей и некие операции над ними.

Например, нам нужно взять подразделения компании, перенести часть нужных нам полей, а, также, налету, создать поле, в котором лежит полный путь до этого подразделения в дереве (например, "Бизнес-юнит 3/Департамент 2/Подразделение 1"). Представим себе, что в исходном сообщении эти данные есть, но в виде массива родительских подразделений. То есть нужно взять их названия, правильно отсортировать и соединить в строку.

Какой же интерфейс предоставить программистам, чтобы они могли это сделать? Правильно, формализованный JsonPath (RFC). Конечный пользователь тоже не пострадает, так как сможет, с помощью программистов, натыкать такое на UI.

Когда сервис будет вычитывать сообщение из Kafka, исходное сообщение будет преобразовано, размаплено по нужным полям DBO и помещено в базу. Маппинг, при создании job будет выглядеть примерно так.
{
"id": "$.id",
"1c_id": "$.1c.id",
"full_path": "join(sort($.parents, @.lvl), '/')",
"name": "$.name",
"manager_id": "$.manager.oauth.id",
"filters": [
"$.is_deleted == false",
"$.draft == false"
]
}


Но чтобы сделать этот маппинг, увы, нужно приложить усилия. Дело в том, что стандартная (с некоторых пор) библиотека для работы с json в .NET это System.Text.Json. А он не умеет выбирать узел по JsonPath. Опустим и то, что мало кто из библиотек умеет работать с функциями высшего порядка (см. full_path в примере), но это, со скрипом, можно сделать самому.

Основная задача - получение нужных узлов исходного сообщения в Kafka по выражению JsonPath. Для решения этой задачи можно найти несколько библиотек: непотопляемый Newtonsoft.Json, модный Hyperbee.Json, хмурый JsonCons.Net и популярный JsonPath.Net).

Так как сервис представляется весьма нагруженным, а поиск и преобразования по JsonPath - частыми, нужно выбрать именно ту библиотеку, которая работает быстро и, при этом, потребляет мало памяти. Результаты на скриншоте. Кажется, что Newtonsoft.Json или Hyperbee.Json - весьма неплохой выбор, по скорости и потреблению памяти.

Естественно, все эти библиотеки отличаются функционалом и возможностями расширения (например, в данном примере нужно добавлять свои функции к JsonPath для мутации данных). Тот же Newtonsoft.Json огромная и уважаемая библиотека. Однако, если нужно только парсить JsonPath, то выбор похож на очевидный.

Бенчмарк вот тут.

P.S.: Банчмарки включают в себя создание JsonDocument, JsonNode и JObject, чтобы приблизиться к реальной ситуации. В реальности сервис получает одну из этих структур данных и работает с ней. Если эти штуки предварительно создавать, то, в принципе, результат не изменится. Единственное, что изменится - пропадёт аллокация.
P.P.S.: Пакет Microsoft.AspNetCore.JsonPatch исключён из тестирования, так как основывается на Newtonsoft.Json.
P.P.P.S.: Ребята из Hyperbee.Json, кажется, выложили на nuget библиотеку, которая скомпилирована в Debug. Исправили.
👍12👏43🔥1



tgoop.com/csharp_gepard/155
Create:
Last Update:

JsonPath в .NET #решение

Представим себе, что есть сервис, который умеет получать данные из Kafka и складывать полученные данные в БД. Без программирования, просто декларативным указанием topic и таблицы в БД. То есть:

1. Сервис работает по запросу (job или unit-of-work).
2. При создании job описывается маппинг данных из Kafka в нужную таблицу.
3. Описывается фильтрация и преобразовывает данных из Kafka так, как пользователю удобно. Ну чтобы не заниматься этим при каждом запросе в БД.

То есть, во-первых, нужен вменяемый API, которым удобно пользоваться. Во-вторых, нужно описание маппинга полей сообщения из Kafka в поля Data-base-object (DBO). Ну и всякая фильтрация (например, отсечение удалённых), выбор определённых полей и некие операции над ними.

Например, нам нужно взять подразделения компании, перенести часть нужных нам полей, а, также, налету, создать поле, в котором лежит полный путь до этого подразделения в дереве (например, "Бизнес-юнит 3/Департамент 2/Подразделение 1"). Представим себе, что в исходном сообщении эти данные есть, но в виде массива родительских подразделений. То есть нужно взять их названия, правильно отсортировать и соединить в строку.

Какой же интерфейс предоставить программистам, чтобы они могли это сделать? Правильно, формализованный JsonPath (RFC). Конечный пользователь тоже не пострадает, так как сможет, с помощью программистов, натыкать такое на UI.

Когда сервис будет вычитывать сообщение из Kafka, исходное сообщение будет преобразовано, размаплено по нужным полям DBO и помещено в базу. Маппинг, при создании job будет выглядеть примерно так.

{
"id": "$.id",
"1c_id": "$.1c.id",
"full_path": "join(sort($.parents, @.lvl), '/')",
"name": "$.name",
"manager_id": "$.manager.oauth.id",
"filters": [
"$.is_deleted == false",
"$.draft == false"
]
}


Но чтобы сделать этот маппинг, увы, нужно приложить усилия. Дело в том, что стандартная (с некоторых пор) библиотека для работы с json в .NET это System.Text.Json. А он не умеет выбирать узел по JsonPath. Опустим и то, что мало кто из библиотек умеет работать с функциями высшего порядка (см. full_path в примере), но это, со скрипом, можно сделать самому.

Основная задача - получение нужных узлов исходного сообщения в Kafka по выражению JsonPath. Для решения этой задачи можно найти несколько библиотек: непотопляемый Newtonsoft.Json, модный Hyperbee.Json, хмурый JsonCons.Net и популярный JsonPath.Net).

Так как сервис представляется весьма нагруженным, а поиск и преобразования по JsonPath - частыми, нужно выбрать именно ту библиотеку, которая работает быстро и, при этом, потребляет мало памяти. Результаты на скриншоте. Кажется, что Newtonsoft.Json или Hyperbee.Json - весьма неплохой выбор, по скорости и потреблению памяти.

Естественно, все эти библиотеки отличаются функционалом и возможностями расширения (например, в данном примере нужно добавлять свои функции к JsonPath для мутации данных). Тот же Newtonsoft.Json огромная и уважаемая библиотека. Однако, если нужно только парсить JsonPath, то выбор похож на очевидный.

Бенчмарк вот тут.

P.S.: Банчмарки включают в себя создание JsonDocument, JsonNode и JObject, чтобы приблизиться к реальной ситуации. В реальности сервис получает одну из этих структур данных и работает с ней. Если эти штуки предварительно создавать, то, в принципе, результат не изменится. Единственное, что изменится - пропадёт аллокация.
P.P.S.: Пакет Microsoft.AspNetCore.JsonPatch исключён из тестирования, так как основывается на Newtonsoft.Json.
P.P.P.S.: Ребята из Hyperbee.Json, кажется, выложили на nuget библиотеку, которая скомпилирована в Debug. Исправили.

BY C# Heppard




Share with your friend now:
tgoop.com/csharp_gepard/155

View MORE
Open in Telegram


Telegram News

Date: |

How to create a business channel on Telegram? (Tutorial) Telegram Channels requirements & features When choosing the right name for your Telegram channel, use the language of your target audience. The name must sum up the essence of your channel in 1-3 words. If you’re planning to expand your Telegram audience, it makes sense to incorporate keywords into your name. Ng, who had pleaded not guilty to all charges, had been detained for more than 20 months. His channel was said to have contained around 120 messages and photos that incited others to vandalise pro-government shops and commit criminal damage targeting police stations. With the “Bear Market Screaming Therapy Group,” we’ve now transcended language.
from us


Telegram C# Heppard
FROM American