Использование JSON_VALUE JSON_QUERY для создания нового JSON

#json #sql-server

Вопрос:

Мне было интересно, можно ли будет изменить формат JSON и вернуть его в качестве JSON. У меня есть JSON, который в упрощенной форме выглядит так:

  • Имя
  • Подробные сведения
    • fieldId
    • Значение поля
  • Другое
    • ID
    • Ценность

И хотел бы вернуться:

  • Имя
  • Подробные сведения
    • fieldId
    • Значение поля

Я могу вернуть имя и сведения с JSON_VALUE помощью и JSON_QUERY , но хотел бы, чтобы это было одно объединенное поле JSON.

 create table #test (
  [id] int,
  [json] varchar(max)
);

insert into #test (id, json) values (1, '{
  "Name": "Test 1",
  "Details": [
    {
      "fieldId": "100",
      "fieldValue": "ABC"
    }],
  "Other": [
    {
      "Id": "1",
      "Value": "ABC"
    }]
}');

insert into #test (id, json) values (2, '{
  "Name": "Test 2",
  "Details": [
    {
      "fieldId": "101",
      "fieldValue": "ABCD"
    }],
  "Other": [
    {
      "Id": "2",
      "Value": "ABCD"
    }]
}');

select id, JSON_VALUE(json, '$.Name'), JSON_QUERY(json, '$.Details')
from #test
 

Ответ №1:

В качестве дополнительной опции вы можете проанализировать JSON с OPENJSON() помощью и явной схемы (определения столбцов), а затем снова создать новый JSON:

 SELECT
   id,
   newjson = (
      SELECT Name, Details 
      FROM OPENJSON(json) WITH (
         Name varchar(max) '$.Name',
         Details nvarchar(max) '$.Details' AS JSON
      )
      FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
   )
FROM #test
 

И тот же подход с JSON_VALUE() и JSON_QUERY() :

 SELECT 
  id, 
  newjson = (
     SELECT JSON_VALUE(json, '$.Name') AS [Name], JSON_QUERY(json, '$.Details') AS [Details]
     FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
  )   
FROM #test
 

Ответ №2:

Одним из решений является использование JSON_MODIFY для повторного построения JSON:

 SELECT
    id,
    JSON_MODIFY(
        JSON_MODIFY(
            '{}',
            '$.Name',
            JSON_VALUE(json, '$.Name')
        ),
        '$.Details',
        JSON_QUERY(json, '$.Details')
    ) AS new_json
FROM #test
 

Альтернативным вариантом было бы удалить Other узел с помощью JSON_MODIFY , но вы должны знать имя узла(ов) для удаления.