К списку

XML & JSON in SQL Server

21 декабря 2020

For XML Extension

Преобразование данных из реляционной модели в XML

Зачастую необходимо делать выгрузку из реляционной БД в формате XML для передачи их некоторому приложению или сервису.

В SQL Server это можно выполнить с помощью инструкции FOR XML, добавляемой в конец оператора SELECT.

Пример логической модели данных:

For XML Explicit

Первая попытка Microsoft предоставить инструмент генерации XML заданной структуры из реляционных данных.

Имеет ряд недостатков (прежде всего, сложность описания структуры генерируемого XML, нечитабельность и “тормознутость” кода) и сейчас практически не используется.

Режим EXPLICIT преобразует набор строк, получаемый в результате выполнения запроса, в XML-документ. Для того чтобы режим EXPLICIT создал XML-документ, набор строк должен иметь определенный формат.

Запрос должен создавать следующие два столбца метаданных:

  • первый столбец должен предоставлять номер тега текущего элемента (целочисленного типа), с именем столбца Tag. В запросе должен быть указан уникальный номер тега для каждого элемента, который будет создан из набора строк;
  • второй столбец должен задавать номер тега для родительского элемента, и этот столбец должен иметь имя Parent. Таким образом, столбцы Tag и Parent предоставляют сведения об иерархии.

Значение 0 или NULL в столбце Parent указывает на то, что у соответствующего элемента нет родителя. Такой элемент добавляется в XML в качестве элемента верхнего уровня.

Имена столбцов в результирующем наборе строк должны быть заданы с использованием описанного ниже формата:

ElementName!TagNumber!AttributeName

Далее следует описание частей формата.

ElementName
Результирующий общий идентификатор элемента. Например, если Swimmer задано в качестве ElementName, формируется элемент <Swimmer>.

TagNumber
Уникальное значение тега, присвоенное элементу. Это значение с помощью двух метастолбцов, Tag и Parent, определяет вложенность элементов в результирующем XML.

AttributeName
Предоставляет имя создаваемого атрибута для указанного элемента ElementName

Для понимания того, как универсальная таблица, сформированная запросом, преобразуется в результат XML, предположим, что написан запрос, который создает универсальную таблицу.

Обратите внимание на следующие особенности этой универсальной таблицы:

Первые два столбца Tag и Parent являются метастолбцами. Эти значения определяют иерархию.

Имена столбцов задаются особым образом, как описано выше в данном подразделе.

При формировании XML из этой универсальной таблицы данные таблицы секционируются вертикально на группы столбцов. Группировка определяется на основании значения Tag и имен столбцов. При конструировании XML логика обработки выбирает одну группу столбцов для каждой строки и создает элемент.

Так как существует два уровня в иерархии, следует написать запросы SELECT для каждого из них и применить предложение UNION ALL.

Подробнее о использовании режима EXPLICIT совместно с предложением FOR XML смотрите в справке по адресу.

In [1]:

use tempdb
go

select  1             as Tag,
        NULL          as Parent,
        s.FirstName   as [Swimmer!1!FirstName],
        s.LastName    as [Swimmer!1!LastName],
        s.YearOfBirth as [Swimmer!1!YearOfBirth],
        NULL          as [Team!2!City], 
        NULL          as [Team!2!Name],
        NULL          as [Coach!3!FirstName],
        NULL          as [Coach!3!LastName]
from   dbo.Swimmer s
union all 
select  2             as Tag,
        1             as Parent,
        s.FirstName,
        s.LastName,
        s.YearOfBirth,
        sc.City, 
        sc.[Name],
        NULL,
        NULL
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
union all 
select  3             as Tag,
        1             as Parent,
        s.FirstName,
        s.LastName,
        s.YearOfBirth,
        NULL, 
        NULL,
        c.FirstName,
        c.LastName
from dbo.Swimmer s
left join dbo.SwimmerCoach xref on xref.SwimmerID = s.SwimmerID 
inner join dbo.Coach c          on c.CoachID = xref.CoachID
order by 3, 4, 5, 6, 7, 8, 9
for xml explicit

Commands completed successfully.
Total execution time: 00:00:00.0019871
(21 rows affected)
Total execution time: 00:00:00.0039637

Out[1]:
<Swimmer FirstName="Gleb" LastName="Bondarec" YearOfBirth="2007">
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
<Team City="Минск" Name="ГЦОР Трактор"/>
</Swimmer>
<Swimmer FirstName="Алексей" LastName="Рылько" YearOfBirth="2005">
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
</Swimmer>
<Swimmer FirstName="Анна" LastName="Высоцкая" YearOfBirth="2007">
<Coach FirstName="Евгения" LastName="Жукова"/>
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
</Swimmer>
<Swimmer FirstName="Илья" LastName="Гавриленко" YearOfBirth="2006">
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
<Team City="Минск" Name="ГЦОР Трактор"/>
</Swimmer>
<Swimmer FirstName="Максим" LastName="Кликушин" YearOfBirth="2007">
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
<Team City="Минск" Name="ГЦОР Трактор"/>
</Swimmer>
<Swimmer FirstName="Матвей" LastName="Данкевич" YearOfBirth="2006">
<Team City="Молодечно" Name="СК Олимпик-2011"/>
</Swimmer>
<Swimmer FirstName="Никита" LastName="Клюй" YearOfBirth="2005">
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
</Swimmer>

For XML Raw

Cамый простой и быстрый способ генерации XML.

Используется в случае, если нет необходимости в нетривиальном формате создаваемого XML документа. В этом режиме каждая строка результирующего набора преобразуется в отдельный элемент <row>.

In [2]:

use tempdb
go

select  s.FirstName   swimmer_first_name,
        s.LastName    swimmer_last_name,
        s.YearOfBirth swimmer_year_of_birth,
        sc.City, 
        sc.[Name],
        c.FirstName   coach_first_name,
        c.LastName    coach_last_name
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
left join dbo.SwimmerCoach xref on xref.SwimmerID = s.SwimmerID 
left join dbo.Coach c          on c.CoachID = xref.CoachID
order by 1, 2, 3, 4, 5, 6, 7
for xml raw

Commands completed successfully.
Total execution time: 00:00:00.0023278
(7 rows affected)
Total execution time: 00:00:00.0162922

Out[2]:
<row swimmer_first_name="Анна" swimmer_last_name="Высоцкая" swimmer_year_of_birth="2006" City="Минск" Name="ДЮСШ Янтарь" coach_first_name="Евгения" coach_last_name="Жукова"/>
<row swimmer_first_name="Илья" swimmer_last_name="Гавриленко" swimmer_year_of_birth="2006" City="Минск" Name="ГЦОР Трактор" coach_first_name="Алла" coach_last_name="Усенок"/>
<row swimmer_first_name="Илья" swimmer_last_name="Гавриленко" swimmer_year_of_birth="2006" City="Минск" Name="ГЦОР Трактор" coach_first_name="Виталий" coach_last_name="Барташевич"/>
<row swimmer_first_name="Максим" swimmer_last_name="Кликушин" swimmer_year_of_birth="2007" City="Минск" Name="ГЦОР Трактор" coach_first_name="Алла" coach_last_name="Усенок"/>
<row swimmer_first_name="Максим" swimmer_last_name="Кликушин" swimmer_year_of_birth="2007" City="Минск" Name="ГЦОР Трактор" coach_first_name="Виталий" coach_last_name="Барташевич"/>
<row swimmer_first_name="Матвей" swimmer_last_name="Данкевич" swimmer_year_of_birth="2006" City="Молодечно" Name="СК Олимпик-2011"/>
<row swimmer_first_name="Никита" swimmer_last_name="Клюй" swimmer_year_of_birth="2005" City="Минск" Name="ДЮСШ Янтарь"/>

For XML Auto

Чуть более сложный и одновременно чуть более мощный способ генерации XML.

Позволяет стандартным (шаблонным) способом организовывать нетривиальную иерархическую структуру XML.

In [3]:

use tempdb
go

select  s.FirstName   swimmer_first_name,
        s.LastName    swimmer_last_name,
        s.YearOfBirth swimmer_year_of_birth,
        sc.City, 
        sc.[Name],
        c.FirstName   coach_first_name,
        c.LastName    coach_last_name
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
left join dbo.SwimmerCoach xref on xref.SwimmerID = s.SwimmerID 
left join dbo.Coach c          on c.CoachID = xref.CoachID
order by 1, 2, 3, 4, 5, 6, 7
for xml auto

Commands completed successfully.
Total execution time: 00:00:00.0018639
(7 rows affected)
Total execution time: 00:00:00.0152012

Out[3]:
<s swimmer_first_name="Анна" swimmer_last_name="Высоцкая" swimmer_year_of_birth="2006">
<sc City="Минск" Name="ДЮСШ Янтарь">
<c coach_first_name="Евгения" coach_last_name="Жукова"/>
</sc>
</s>
<s swimmer_first_name="Илья" swimmer_last_name="Гавриленко" swimmer_year_of_birth="2006">
<sc City="Минск" Name="ГЦОР Трактор">
<c coach_first_name="Алла" coach_last_name="Усенок"/>
<c coach_first_name="Виталий" coach_last_name="Барташевич"/>
</sc>
</s>
<s swimmer_first_name="Максим" swimmer_last_name="Кликушин" swimmer_year_of_birth="2007">
<sc City="Минск" Name="ГЦОР Трактор">
<c coach_first_name="Алла" coach_last_name="Усенок"/>
<c coach_first_name="Виталий" coach_last_name="Барташевич"/>
</sc>
</s>
<s swimmer_first_name="Матвей" swimmer_last_name="Данкевич" swimmer_year_of_birth="2006">
<sc City="Молодечно" Name="СК Олимпик-2011">
<c/>
</sc>
</s>
<s swimmer_first_name="Никита" swimmer_last_name="Клюй" swimmer_year_of_birth="2005">
<sc City="Минск" Name="ДЮСШ Янтарь">
<c/>
</sc>
</s>

For XML Path

Самый гибкий способ генерации XML практически любой структуры (и поэтому медленный!)

Тот же XML что и в примере про xml explicit:

In [4]:

use tempdb
go

select  s.FirstName   [Swimmer/@FirstName],
        s.LastName    [Swimmer/@LastName],
        s.YearOfBirth [Swimmer/@YearOfBirth],
        sc.City       [Swimmer/Team/@City], 
        sc.[Name]     [Swimmer/Team/@Name],
        (
           select
               c.FirstName   [@FirstName],
               c.LastName    [@LastName]
           from dbo.SwimmerCoach xref 
           inner join dbo.Coach c on c.CoachID = xref.CoachID
           where xref.SwimmerID = s.SwimmerID 
           for xml path('Coach'), type
        )             [Swimmer]
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
order by 1, 2, 3, 4, 5
for xml path('')

Commands completed successfully.
Total execution time: 00:00:00.0013479
(7 rows affected)
Total execution time: 00:00:00.0098099

Out[4]:
<Swimmer FirstName="Gleb" LastName="Bondarec" YearOfBirth="2007">
<Team City="Минск" Name="ГЦОР Трактор"/>
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
</Swimmer>
<Swimmer FirstName="Алексей" LastName="Рылько" YearOfBirth="2005">
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
</Swimmer>
<Swimmer FirstName="Анна" LastName="Высоцкая" YearOfBirth="2007">
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
<Coach FirstName="Евгения" LastName="Жукова"/>
</Swimmer>
<Swimmer FirstName="Илья" LastName="Гавриленко" YearOfBirth="2006">
<Team City="Минск" Name="ГЦОР Трактор"/>
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
</Swimmer>
<Swimmer FirstName="Максим" LastName="Кликушин" YearOfBirth="2007">
<Team City="Минск" Name="ГЦОР Трактор"/>
<Coach FirstName="Алла" LastName="Усенок"/>
<Coach FirstName="Виталий" LastName="Барташевич"/>
</Swimmer>
<Swimmer FirstName="Матвей" LastName="Данкевич" YearOfBirth="2006">
<Team City="Молодечно" Name="СК Олимпик-2011"/>
</Swimmer>
<Swimmer FirstName="Никита" LastName="Клюй" YearOfBirth="2005">
<Team City="Minsk" Name="ДЮСШ Янтарь"/>
</Swimmer>

Опции elements и root:

In [5]:

use tempdb
go

select  s.FirstName,
        s.LastName,
        s.YearOfBirth,
        sc.City       Team_City, 
        sc.[Name]     Team_Name
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
order by 1, 2, 3, 4, 5
for xml raw('element'), root('persons'), elements
Commands completed successfully.
Total execution time: 00:00:00.0019112
(7 rows affected)
Total execution time: 00:00:00.0079248

Out[5]:
<persons>
<element>
<FirstName>Gleb</FirstName>
<LastName>Bondarec</LastName>
<YearOfBirth>2007</YearOfBirth>
<Team_City>Минск</Team_City>
<Team_Name>ГЦОР Трактор</Team_Name>
</element>
<element>
<FirstName>Алексей</FirstName>
<LastName>Рылько</LastName>
<YearOfBirth>2005</YearOfBirth>
<Team_City>Minsk</Team_City>
<Team_Name>ДЮСШ Янтарь</Team_Name>
</element>
<element>
<FirstName>Анна</FirstName>
<LastName>Высоцкая</LastName>
<YearOfBirth>2007</YearOfBirth>
<Team_City>Minsk</Team_City>
<Team_Name>ДЮСШ Янтарь</Team_Name>
</element>
<element>
<FirstName>Илья</FirstName>
<LastName>Гавриленко</LastName>
<YearOfBirth>2006</YearOfBirth>
<Team_City>Минск</Team_City>
<Team_Name>ГЦОР Трактор</Team_Name>
</element>
<element>
<FirstName>Максим</FirstName>
<LastName>Кликушин</LastName>
<YearOfBirth>2007</YearOfBirth>
<Team_City>Минск</Team_City>
<Team_Name>ГЦОР Трактор</Team_Name>
</element>
<element>
<FirstName>Матвей</FirstName>
<LastName>Данкевич</LastName>
<YearOfBirth>2006</YearOfBirth>
<Team_City>Молодечно</Team_City>
<Team_Name>СК Олимпик-2011</Team_Name>
</element>
<element>
<FirstName>Никита</FirstName>
<LastName>Клюй</LastName>
<YearOfBirth>2005</YearOfBirth>
<Team_City>Minsk</Team_City>
<Team_Name>ДЮСШ Янтарь</Team_Name>
</element>
</persons>

OpenXML

Преобразование данных из XML в реляционный формат

In [6]:

declare @hdoc int,
        @xml  varchar(1000)

set @xml = '
<root>
  <Person City="Bothell" Address="New address">
    <Name>
      <FirstName>Syed</FirstName>
      <LastName>Abbas</LastName>
    </Name>
  </Person>
  <Person City="Carnation" Address="9752 Jeanne Circle">
    <Name>
      <FirstName>Kim</FirstName>
      <LastName>Abercrombie</LastName>
    </Name>
  </Person>
</root>  
'

--получаем дескриптор XML документа
exec sp_xml_preparedocument @hdoc OUTPUT, @xml

select * 
from OpenXML(@hdoc,'/root/Person',2)
    with(
            FirstName varchar(20) 'Name/FirstName',
            LastName varchar(20)  'Name/LastName',
            City varchar(100)     '@City'
        ) X

--освобождаем ресурсы
exec sp_xml_removedocument @hdoc

(2 rows affected)
Total execution time: 00:00:00.0176054

Out[6]:

For JSON Extention

Преобразование данных из реляционной модели в JSON

Аналогично тому как мы можем генерировать XML, мы можем и с JSON:

In [7]:

use tempdb
go

select  s.FirstName   [Swimmer.FirstName],
        s.LastName    [Swimmer.LastName],
        s.YearOfBirth [Swimmer.YearOfBirth],
        sc.City       [Team.City], 
        sc.[Name]     [Team.Name],
        (
           select
               c.FirstName   [FirstName],
               c.LastName    [LastName]
           from dbo.SwimmerCoach xref 
           inner join dbo.Coach c on c.CoachID = xref.CoachID
           where xref.SwimmerID = s.SwimmerID 
           for json path
        )             [Coach]
from dbo.Swimmer s
left join dbo.SwimmingClub sc   on sc.SwimmingClubID = s.SwimmingClubID
order by 1, 2, 3, 4, 5
for json path
Commands completed successfully.
Total execution time: 00:00:00.0019346

Out[7]:
[
{"Swimmer":{"FirstName":"Gleb","LastName":"Bondarec","YearOfBirth":2007},"Team":{"City":"Минск","Name":"ГЦОР Трактор"},"Coach":[{"FirstName":"Алла","LastName":"Усенок"},{"FirstName":"Виталий","LastName":"Барташевич"}]},
{"Swimmer":{"FirstName":"Алексей","LastName":"Рылько","YearOfBirth":2005},"Team":{"City":"Minsk","Name":"ДЮСШ Янтарь"}},
{"Swimmer":{"FirstName":"Анна","LastName":"Высоцкая","YearOfBirth":2007},"Team":{"City":"Minsk","Name":"ДЮСШ Янтарь"},"Coach":[{"FirstName":"Евгения","LastName":"Жукова"}]},
{"Swimmer":{"FirstName":"Илья","LastName":"Гавриленко","YearOfBirth":2006},"Team":{"City":"Минск","Name":"ГЦОР Трактор"},"Coach":[{"FirstName":"Алла","LastName":"Усенок"},{"FirstName":"Виталий","LastName":"Барташевич"}]},
{"Swimmer":{"FirstName":"Максим","LastName":"Кликушин","YearOfBirth":2007},"Team":{"City":"Минск","Name":"ГЦОР Трактор"},"Coach":[{"FirstName":"Алла","LastName":"Усенок"},{"FirstName":"Виталий","LastName":"Барташевич"}]},
{"Swimmer":{"FirstName":"Матвей","LastName":"Данкевич","YearOfBirth":2006},"Team":{"City":"Молодечно","Name":"СК Олимпик-2011"}},
{"Swimmer":{"FirstName":"Никита","LastName":"Клюй","YearOfBirth":2005},"Team":{"City":"Minsk","Name":"ДЮСШ Янтарь"}}
]
Total execution time: 00:00:00.0079642

OpenJSON

Преобразование данных из JSON в реляционный формат

OPENJSON — функция с табличным значением, которая выполняет синтаксический анализ текста JSON и возвращает объекты и свойства из входных данных JSON в виде строк и столбцов.

Link

In [8]:

declare @json nvarchar(4000) 
set @json = N'
{
    "FirstName": "Илья",
    "LastName": "Гавриленко",
    "YearOfBirth": 2006,
    "Gender": "м",
    "Club": {
        "Name": "ГЦОР Трактор",
        "City": "Минск"
    },
    "Category": "II",
    "Coach": [
        {"FirstName": "Алла", "LastName": "Усенок"},
        {"FirstName": "Виталий", "LastName": "Барташевич"}
    ]
} 
'

select *
from openjson(@json) 

--извлечь все атрибуты, в том числе, более чем 1 уровня вложенности
select *
from openjson(@json) 
    with 
        (
            FirstName       nvarchar(20)    N'$.FirstName',
            LastName        nvarchar(30)    N'$.LastName',
            YearOfBirth     smallint        N'$.YearOfBirth',
            Gender          nchar(1)        N'$.Gender',
            Category        nvarchar(20)    N'$.Category',
            ClubCity        nvarchar(50)    N'$.Club.City',
            ClubName        nvarchar(100)   N'$.Club.Name',
            Coach           nvarchar(max)   N'$.Coach'        as json
        )  js

(7 rows affected)
(1 row affected)
Total execution time: 00:00:00.0173023

Out[8]:

Out[8]:

Если вы хотите получить данные из вложенного массива JSON, можно использовать корреляционный вызов OPENJSON  с помощью CROSS APPLY или OUTER APPLY:

In [9]:

declare @json nvarchar(4000) 
set @json = N'
{
    "FirstName": "Илья",
    "LastName": "Гавриленко",
    "YearOfBirth": 2006,
    "Gender": "м",
    "Club": {
        "Name": "ГЦОР Трактор",
        "City": "Минск"
    },
    "Category": "II",
    "Coach": [
        {"FirstName": "Алла", "LastName": "Усенок"},
        {"FirstName": "Виталий", "LastName": "Барташевич"}
    ]
} 
'

--извлечь все атрибуты, в том числе, более чем 1 уровня вложенности
select      js.FirstName,
            js.LastName,
            js.YearOfBirth,
            js.Gender,
            js.Category,
            js.ClubCity,
            js.ClubName,
            jsc.CoachFirstName, 
            jsc.CoachLastName
from openjson(@json) 
    with 
        (
            FirstName       nvarchar(20)    N'$.FirstName',
            LastName        nvarchar(30)    N'$.LastName',
            YearOfBirth     smallint        N'$.YearOfBirth',
            Gender          nchar(1)        N'$.Gender',
            Category        nvarchar(20)    N'$.Category',
            ClubCity        nvarchar(50)    N'$.Club.City',
            ClubName        nvarchar(100)   N'$.Club.Name',
            Coach           nvarchar(max)   N'$.Coach'        as json
        )  js 
outer apply openjson(js.Coach)        
    with 
        (
            CoachFirstName  nvarchar(20)    N'$.FirstName',
            CoachLastName   nvarchar(30)    N'$.LastName'
        )  jsc

(2 rows affected)
Total execution time: 00:00:00.0071696

Out [9]:

JSON_Value, JSON_Query, JSON_Modify

In [10]:

declare @json nvarchar(4000) 
set @json =	N'
{
    "FirstName": "Илья",
    "LastName": "Гавриленко",
    "YearOfBirth": 2006,
    "Gender": "м",
    "Club": {
        "Name": "ГЦОР Трактор",
        "City": "Минск"
    },
    "Category": "II",
    "Coach": [
        {"FirstName": "Алла", "LastName": "Усенок"},
        {"FirstName": "Виталий", "LastName": "Барташевич"}
    ]
} 
'

select FirstName   = json_value(@json, '$.FirstName'),
       LastName    = json_value(@json, '$.LastName'),
       YearOfBirth = json_value(@json, '$.YearOfBirth'),
       Team        = json_value(@json, '$.Club.City') + ' ' + json_value(@json, '$.Club.Name'),
       YearOfBirth = json_query(@json, '$.Coach')   --json_value не подходит

(1 row affected)
Total execution time: 00:00:00.0046983

Out [10]:

In [11]:

declare @json nvarchar(4000) 
set @json =	N'
{
    "FirstName": "Илья",
    "LastName": "Гавриленко",
    "YearOfBirth": 2006,
    "Gender": "м",
    "Club": {
        "Name": "ГЦОР Трактор",
        "City": "Минск"
    },
    "Category": "II",
    "Coach": [
        {"FirstName": "Алла", "LastName": "Усенок"},
        {"FirstName": "Виталий", "LastName": "Барашевич"}
    ]
} 
'

--корректируем ошибку в фамилии тренера
set @json = json_modify(@json, '$.Coach[1].LastName', N'Барташевич')   

--добавляем дополнительный атрибут
set @json = json_modify(@json, '$.Club.Address', N'Долгобродская улица, 37. ст.м. Тракторный Завод')   

--добавляем дополнительный элемент в массив
set @json = json_modify(
                @json, 
                'append $.Coach', 
                json_query(N'{"FirstName": "Наталья", "LastName": "Бученкова"}', '$')
            )   

select @json
(1 row affected)
Total execution time: 00:00:00.0081801

Out [11]:

{
"FirstName": "Илья",
"LastName": "Гавриленко",
"YearOfBirth": 2006,
"Gender": "м",
"Club": { "Name": "ГЦОР Трактор", "City": "Минск" ,"Address":"Долгобродская улица, 37. ст.м. Тракторный Завод"},
"Category": "II",
"Coach": [ {"FirstName": "Алла", "LastName": "Усенок"}, {"FirstName": "Виталий", "LastName": "Барташевич"} ,
{"FirstName": "Наталья", "LastName": "Бученкова"}]
}

Автор материала – Тимофей Гавриленко, преподаватель Тренинг-центра ISsoft.

Образование: окончил с отличием математический факультет Гомельского Государственного Университета им. Франциска Скорины.

Microsoft Certified Professional (70-464, 70-465).

Работа: c 2011 года работает в компании ISsoft (ETL/BI Developer, Release Manager, Data Analyst/Architect, SQL Training Manager), на протяжении 10 лет до этого выступал как Sysadmin, DBA, Software Engineer.

В свободное время ведет бесплатные образовательные курсы для детей и взрослых, желающих повысить свой уровень компьютерной грамотности и переквалифицироваться в IT-специалиста.