Преобразовать юникод в китайский символ внутри JSON?

#sql #json #sql-server #tsql

Вопрос:

У меня есть некоторые данные в базе данных (sql server 2008) в формате JSON с юникодом, как это:

 {"PCode":"999999","Code":"123","effect":"u4e2du6587u5b57u6e2cu8a66"}
 

u4e2du6587u5b57u6e2cu8a66 являются ли китайские иероглифы, как я могу восстановить данные в китайских иероглифах?

Комментарии:

1. как только китайские иероглифы будут преобразованы в шестнадцатеричные…вы не сможете преобразовать их обратно. ваша колонка должна поддерживать юникод. Я думаю, что вы используете varchar для хранения данных вместо Nvarchar.

2. Каков тип данных столбца и версия SQL Server? Обычно OPENJSON достаточно одного звонка.

3. @ДалеК ответ, который я пробовал

4. @hkguile если вы на самом деле не отвечаете на свой собственный вопрос, вам нужно добавить это в свой вопрос и удалить ответ.

Ответ №1:

Ответ:

Похоже, вы используете SQL Server 2008 (где поддержка JSON недоступна), поэтому одним из возможных подходов является анализ последовательности юникода в формате XML. Обратите внимание, что XML не использует u обозначения, поэтому вам необходимо преобразовать этот текст JSON с помощью ссылки на символы XML amp;#x[0-9a-fA-F]; :

T-SQL:

 DECLARE @text nvarchar(max)
SET @text = N'u4e2du6587u5b57u6e2cu8a66'

DECLARE @xml xml
SET @xml = N'<x>'   STUFF(REPLACE(@text, N'u', N';amp;#x'), 1, 1, N'')   N';</x>'
SELECT @xml.value('(/x)[1]', 'nvarchar(max)') AS [ChineseText]
 

Результат:

 ChineseText
-----------
中文字測試
 

Обратите внимание, что с SQL Server 2016 вы можете легко анализировать JSON с помощью JSON_VALUE() .

 SELECT JSON_VALUE(CONCAT(N'["', @text, N'"]'), '$[0]') AS [ChineseText]
 

Обновить:

Если в JSON есть дополнительные символы, вам необходимо разделить содержимое JSON с помощью XML и u в качестве разделителя:

 DECLARE @text nvarchar(max)
SET @text = N'u4e2dengu6587engu5b57234u6e2cu8a66'

DECLARE @xml xml
SET @xml = CONCAT(STUFF(REPLACE(@text, N'u', N'</x><x>'), 1, 4, N''), N'</x>')
SELECT 
   CONVERT(xml, N'<x>amp;#x'   LEFT(t.value('.', 'nvarchar(max)'), 4)   N';</x>').value('(/x)[1]', 'nvarchar(max)'), 
   STUFF(t.value('.', 'nvarchar(max)'), 1, 4, N'')
FROM @xml.nodes('/x') AS x(t)
FOR XML PATH('')
 

Результат:

 中eng文eng字234測試
 

Комментарии:

1. похоже, у меня нет функции конкатенации

2. @hkguile, вы можете использовать оператор объединения.

3. но все равно нужно передать, если какое-то число/eng внутри строки, например, u4e2dengu6587engu5b57234u6e2cu8a66

4. Хороший ответ, 1 с моей стороны!

Ответ №2:

Есть лучшая практика?

 DECLARE @Text NVARCHAR(MAX)
DECLARE @stringToSplit NVARCHAR(MAX)
DECLARE @returnList TABLE ([Name] [nvarchar] (500))

set @stringToSplit = 'u4e2du6587u5b57u6e2cu8a66'

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX('u', @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX('u', @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  IF @name <> ''
  BEGIN
  INSERT INTO @returnList 
  SELECT NCHAR( CONVERT(INT, CONVERT(VARBINARY,@name, 2) ) )
  END

  SELECT @stringToSplit = SUBSTRING(SUBSTRING(@stringToSplit, @pos 1, LEN(@stringToSplit)-@pos),2,LEN(@stringToSplit))
 END

 INSERT INTO @returnList
 SELECT NCHAR( CONVERT(INT, CONVERT(VARBINARY,@stringToSplit, 2) ) )

 select * from @returnList