Преобразование JSON с помощью SQL — объекта и строки для одного и того же свойства

#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.