#arrays #json #sql-server #data-conversion
#массивы #json #sql-сервер #преобразование данных
Вопрос:
У меня возникла проблема с преобразованием массива JSON в другой формат вывода с помощью SQL Server…
Ввод:
[ { "label": "City", "values": [ "Test City" ] }, { "label": "imgTest", "values": [ { "identifier": "56696553-48F4-4BC5-BB43-FF4F71743EE9", "filename": "file1.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" }, { "identifier": "2D9106D7-71A1-440E-8255-679E8905B32E", "filename": "file2.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } ] } ]
Желаемый результат:
[ { "label": "City", "answer": "Test City" }, { "label": "imgTest", "answer": { "filename": "file1.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } }, { "label": "imgTest", "answer": { "filename": "file2.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } } ]
Проблема, которую я нахожу, заключается в сочетании строки и объекта в качестве свойства «ответ» в выводе.
Обратите внимание, что это всего лишь небольшое подмножество очень вложенных входных данных JSON. Спасибо. Временные таблицы и т. Д. Вполне возможны, так как это, скорее всего, произойдет с помощью хранимой процедуры
Причина, по которой я говорю о SQL, заключается в том, что это технология, с которой я больше всего знаком, и которая успешно использовалась для этих целей в прошлом.
Мой первоначальный подход до появления изображений состоял в том, чтобы создать временную таблицу с различными слоями пар «метки-значения», а затем превратить эту таблицу в json с серией вложенных операторов «для пути json».
Однако, когда я делаю это с данными изображения, предполагается, что содержимое является строкой, поэтому оно экранирует символы, что вызывает проблему при отправке выходных данных в следующее приложение…
Комментарии:
1. В соответствии с руководством по вопросам, пожалуйста, покажите, что вы пробовали, и расскажите нам, что вы нашли (на этом сайте или где-либо еще) и почему это не соответствовало вашим потребностям.
Ответ №1:
По умолчанию FOR JSON
предложение экранирует специальные символы в выводе JSON
, и обычно этого можно избежать с помощью JSON_QUERY()
(как описано в документации …JSON_QUERY возвращает допустимый фрагмент JSON. В результате FOR JSON не экранирует специальные символы в возвращаемом значении JSON_QUERY).
Как вы уже знаете, проблема здесь в том, что $."values"
часть JSON содержит строку и объект. Возможным решением этой проблемы является создание таблицы с двумя столбцами с одинаковым именем и применение FOR JSON AUTO
предложения. Вывод FOR JSON AUTO
определяется сочетанием порядка столбцов в SELECT
предложении и таблиц, на которые есть ссылки в SELECT
предложении, поэтому я не уверен, является ли этот вывод «по замыслу» или просто полезным побочным эффектом. Конечно, если вы включите этот INCLUDE_NULL_VALUES
параметр, результат будет включать значения из обоих столбцов.
JSON:
DECLARE @json nvarchar(max) = N' [ { "label": "City", "values": [ "Test City" ] }, { "label": "imgTest", "values": [ { "identifier": "56696553-48F4-4BC5-BB43-FF4F71743EE9", "filename": "file1.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" }, { "identifier": "2D9106D7-71A1-440E-8255-679E8905B32E", "filename": "file2.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } ] } ]'
T-SQL:
SELECT [label], CASE WHEN ISJSON([value]) = 0 THEN [value] END AS [answer], JSON_QUERY(CASE WHEN ISJSON([value]) = 1 THEN [value] END) AS [answer] FROM ( SELECT j1.[label], j2.[value] FROM OPENJSON(@json) WITH ( [label] nvarchar(100) '$.label', [values] nvarchar(max) '$.values' AS JSON ) j1 OUTER APPLY OPENJSON(j1.[values]) j2 ) t FOR JSON AUTO, INCLUDE_NULL_VALUES
Результат:
[ { "label":"City", "answer":"Test City" }, { "label":"imgTest", "answer":{ "identifier":"56696553-48F4-4BC5-BB43-FF4F71743EE9", "filename":"file1.jpg", "contentType":"image/jpg", "bytes":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } }, { "label":"imgTest", "answer":{ "identifier":"2D9106D7-71A1-440E-8255-679E8905B32E", "filename":"file2.jpg", "contentType":"image/jpg", "bytes":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } } ]
Комментарии:
1. Большое вам спасибо @Zhorov. Я не знал, что JSON АВТОМАТИЧЕСКИ допускает несколько выражений с одним и тем же псевдонимом. ПУТЬ JSON не принимает его, но я могу обойти это требование.
Ответ №2:
попробуй это. Он был протестирован в Visual Studio
var jArray = JArray.Parse(json); foreach (var jObject in jArray) { var data = new Data { Label = jObject["label"].ToString() }; var result = new Listlt;Datagt;(); foreach (var jArr in (JArray)jObject["values"]) { if (jArr.GetType().Name.ToString() == "JValue") data.ShortAnswer = ((JValue)jArr).ToString(); else { if (data.Answer == null) data.Answer = new Listlt;Answergt;(); data.Answer.Add(jArr.ToObjectlt;Answergt;()); } } result.Add(data); }
Результат
[ { "label": "City", "answer": null, "shortAnswer": "Test City" }, { "label": "imgTest", "answer": [ { "filename": "file1.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" }, { "filename": "file2.jpg", "contentType": "image/jpg", "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD wSzIAAAABlBMVEX/// /v7 jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII" } ], "shortAnswer": null } ]
классы
public partial class Data { [JsonProperty("label")] public string Label { get; set; } [JsonProperty("answer")] public Listlt;Answergt; Answer { get; set; } [JsonProperty("shortAnswer")] public string ShortAnswer { get; set; } } public partial class Answer { [JsonProperty("filename")] public string Filename { get; set; } [JsonProperty("contentType")] public string ContentType { get; set; } [JsonProperty("bytes")] public string Bytes { get; set; } }
Комментарии:
1. Спасибо, Серж, но я искал решение для SQL Server. Поскольку вся настройка выполняется в SQL Server, я очень, очень стараюсь избегать технологий переключения…
2. @WouterDeRaeve Речь идет не о Json, а о том, как вы собираетесь его использовать. Json бесполезен, он хорош только для перемещения данных между серверами. Для его использования необходимо десериализовать. Я уже десериализовал существующий json, и он готов к использованию. Но вам придется снова десериализовать другой json.