Выберите последнее значение из массива Json - PullRequest
0 голосов
/ 08 октября 2018

Мне нужно получить последний элемент в массиве в формате JSON.У меня есть этот JSON.

  @json =   
  N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": [
            {
                "choice_id": 205073,
                "choice": "aaaa"
            },
            {
                "choice_id": 205074,
                "choice": "bbbb"
            },
            {
                "choice_id": 205075,
                "choice": "cccc"
            },
            {
                "choice_id": 205076,
                "choice": "dddd"
            }
        ],
    }'  

И я хотел бы получить

  @json =   
  N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": {
              "choice_id": 205076,
              "choice": "dddd"
        }
    }

Как мне достичь этого результата?

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

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

Итак, давайте объявим нашу переменную:

DECLARE @json NVARCHAR(MAX) = N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": [
            {
                "choice_id": 205073,
                "choice": "aaaa"
            },
            {
                "choice_id": 205074,
                "choice": "bbbb"
            },
            {
                "choice_id": 205075,
                "choice": "cccc"
            },
            {
                "choice_id": 205076,
                "choice": "dddd"
            }
        ]
    }'

Теперь вы можете использовать комбинацию OPENJSON() и FOR JSON, чтобы получитьпоследняя запись в массиве.

SELECT jsonfield = CAST((
                            SELECT TOP 1
                                j.solution
                                ,o.choice_id
                                ,o.choice
                            FROM
                                OPENJSON(@json)
                                WITH
                                (
                                    solution VARCHAR(MAX) '$.solution'
                                    ,options NVARCHAR(MAX) '$.options' AS JSON
                                ) j
                            CROSS APPLY
                                OPENJSON(options)
                                WITH
                                (
                                    choice_id INT '$.choice_id'
                                    ,choice VARCHAR(4) '$.choice'
                                ) o
                            ORDER BY o.choice_id DESC
                            FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
                        ) AS NVARCHAR(MAX))

РЕДАКТИРОВАТЬ:

Или вы можете использовать этот запрос, если вы не хотите упорядочить по любому из значений узла:

SELECT jsonfield = CAST((
                            SELECT TOP 1
                                j.solution
                                --,o.*
                                ,c.choice_id
                                ,c.choice
                            FROM OPENJSON(@json)
                            WITH
                                (
                                    solution VARCHAR(MAX) '$.solution'
                                    ,options NVARCHAR(MAX) '$.options' AS JSON
                                ) j
                            CROSS APPLY OPENJSON(options) o
                            CROSS APPLY OPENJSON(o.Value) 
                            WITH (
                                    choice_id int '$.choice_id',
                                    choice varchar(4) '$.choice'
                                    ) c
                            ORDER BY [key] DESC
                            FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
                        ) AS NVARCHAR(MAX))
0 голосов
/ 08 октября 2018

Вы можете попробовать это

DECLARE @json NVARCHAR(MAX) =   
N'{ 
    "solution": "xxxxxxxxxxxxxxxxxxxxx",
    "options": [
        {
            "choice_id": 205073,
            "choice": "aaaa"
        },
        {
            "choice_id": 205074,
            "choice": "bbbb"
        },
        {
            "choice_id": 205075,
            "choice": "cccc"
        },
        {
            "choice_id": 205076,
            "choice": "dddd"
        }
    ]
}';

SELECT TOP 1 
         A.solution
        ,JSON_QUERY(B.[value]) AS options
FROM OPENJSON(@json) WITH (solution nvarchar(max), options NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.options) B
ORDER BY B.[key] DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;

Результат

{"solution":"xxxxxxxxxxxxxxxxxxxxx"
,"options":{
            "choice_id": 205076,
            "choice": "dddd"
           }
}

Некоторое объяснение

FROM OPENJSON погрузится в ваш JSON и найдет top-уровень элементов.Мы извлекаем solution как есть и указываем AS JSON для options, чтобы указать, что это значение будет позже обрабатываться как JSON.

CROSS APPLY вызовет OPENJSON снова, но на этот раз против options, и мы вернем массив.Столбец key - это порядковый номер в массиве, поэтому мы можем использовать TOP 1 и ORDER BY key DESC, чтобы получить последний элемент в массиве.

Прежде чем мы сможем повторно собрать этот запрос в JSONмы должны обернуть B.value с JSON_QUERY().В противном случае мы увидели бы экранированные символы, такие как \t или \r\n в JSON.Причина: без этого JSON-строка будет восприниматься не как JSON-строка, а как любая другая строка и будет упакована в результат как одно текстовое значение.

0 голосов
/ 08 октября 2018

Вы можете либо уничтожить с помощью OPENJSON и повторно собрать документ FOR JSON (см. Ответ @ digital.aaron), либо использовать JSON_MODIFY, например:

 declare @json nvarchar(max) =   
  N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": [
            {
                "choice_id": 205073,
                "choice": "aaaa"
            },
            {
                "choice_id": 205074,
                "choice": "bbbb"
            },
            {
                "choice_id": 205075,
                "choice": "cccc"
            },
            {
                "choice_id": 205076,
                "choice": "dddd"
            }
        ]
    }'  


declare @options nvarchar(max) = (
    select top 1 value 
    from openjson(@json,'$.options')
    order by [key] desc 
);

set @json = json_modify(@json, '$.options', json_query(@options))

select  @json

Выходы

{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": {
                "choice_id": 205076,
                "choice": "dddd"
            }
    }

Обратите внимание, что функция JSON_QUERY также используется для анализа строки во фрагмент JSON.Без этого значение в @options будет вставлено как одно строковое значение вместо объекта json.

...