我使用的是SQL Server 2014。我不能使用openjson
读取以下数组并将其转换为表结构。我的数组如下所示。它可以有2个以上的对象。我在表(tableA
)中还有其他一些列以及数组列:
[{"Id":1725,"Number":"12345","qty":1,"Block":true},
{"Id":125,"Number":"1234544","qty":1,"Block":true}]
已在下面创建函数。
但当我为我的表运行它时,它返回空白,因为-
SELECT
dbo.fn_parse_json2xml(X.jsoncolumn) AS XML_Column
FROM
tableA AS X;
我不能让它工作,如果我遗漏了什么,我提前道歉。
CREATE FUNCTION dbo.fn_parse_json2xml(
@json varchar(max)
)
RETURNS xml
AS
BEGIN;
DECLARE @output varchar(max), @key varchar(max), @value varchar(max),
@recursion_counter int, @offset int, @nested bit, @array bit,
@tab char(1)=CHAR(9), @cr char(1)=CHAR(13), @lf char(1)=CHAR(10);
--- Clean up the JSON syntax by removing line breaks and tabs and
--- trimming the results of leading and trailing spaces:
SET @json=LTRIM(RTRIM(
REPLACE(REPLACE(REPLACE(@json, @cr, ''), @lf, ''), @tab, '')));
--- Sanity check: If this is not valid JSON syntax, exit here.
IF (LEFT(@json, 1)!='{' OR RIGHT(@json, 1)!='}')
RETURN '';
--- Because the first and last characters will, by definition, be
--- curly brackets, we can remove them here, and trim the result.
SET @json=LTRIM(RTRIM(SUBSTRING(@json, 2, LEN(@json)-2)));
SELECT @output='';
WHILE (@json!='') BEGIN;
--- Look for the first key which should start with a quote.
IF (LEFT(@json, 1)!='"')
RETURN 'Expected quote (start of key name). Found "'+
LEFT(@json, 1)+'"';
--- .. and end with the next quote (that isn't escaped with
--- and backslash).
SET @key=SUBSTRING(@json, 2,
PATINDEX('%[^\\]"%', SUBSTRING(@json, 2, LEN(@json))+' "'));
--- Truncate @json with the length of the key.
SET @json=LTRIM(SUBSTRING(@json, LEN(@key)+3, LEN(@json)));
--- The next character should be a colon.
IF (LEFT(@json, 1)!=':')
RETURN 'Expected ":" after key name, found "'+
LEFT(@json, 1)+'"!';
--- Truncate @json to skip past the colon:
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json)));
--- If the next character is an angle bracket, this is an array.
IF (LEFT(@json, 1)='[')
SELECT @array=1, @json=LTRIM(SUBSTRING(@json, 2, LEN(@json)));
IF (@array IS NULL) SET @array=0;
WHILE (@array IS NOT NULL) BEGIN;
SELECT @value=NULL, @nested=0;
--- The first character of the remainder of @json indicates
--- what type of value this is.
--- Set @value, depending on what type of value we're looking at:
---
--- 1. A new JSON object:
--- To be sent recursively back into the parser:
IF (@value IS NULL AND LEFT(@json, 1)='{') BEGIN;
SELECT @recursion_counter=1, @offset=1;
WHILE (@recursion_counter!=0 AND @offset<LEN(@json)) BEGIN;
SET @offset=@offset+
PATINDEX('%[{}]%', SUBSTRING(@json, @offset+1,
LEN(@json)));
SET @recursion_counter=@recursion_counter+
(CASE SUBSTRING(@json, @offset, 1)
WHEN '{' THEN 1
WHEN '}' THEN -1 END);
END;
SET @value=CAST(
dbo.fn_parse_json2xml(LEFT(@json, @offset))
AS varchar(max));
SET @json=SUBSTRING(@json, @offset+1, LEN(@json));
SET @nested=1;
END
--- 2a. Blank text (quoted)
IF (@value IS NULL AND LEFT(@json, 2)='""')
SELECT @value='', @json=LTRIM(SUBSTRING(@json, 3,
LEN(@json)));
--- 2b. Other text (quoted, but not blank)
IF (@value IS NULL AND LEFT(@json, 1)='"') BEGIN;
SET @value=SUBSTRING(@json, 2,
PATINDEX('%[^\\]"%',
SUBSTRING(@json, 2, LEN(@json))+' "'));
SET @json=LTRIM(
SUBSTRING(@json, LEN(@value)+3, LEN(@json)));
END;
--- 3. Blank (not quoted)
IF (@value IS NULL AND LEFT(@json, 1)=',')
SET @value='';
--- 4. Or unescaped numbers or text.
IF (@value IS NULL) BEGIN;
SET @value=LEFT(@json,
PATINDEX('%[,}]%', REPLACE(@json, ']', '}')+'}')-1);
SET @json=SUBSTRING(@json, LEN(@value)+1, LEN(@json));
END;
--- Append @key and @value to @output:
SET @output=@output+@lf+@cr+
REPLICATE(@tab, @@NESTLEVEL-1)+
'<'+@key+'>'+
ISNULL(REPLACE(
REPLACE(@value, '\"', '"'), '\\', '\'), '')+
(CASE WHEN @nested=1
THEN @lf+@cr+REPLICATE(@tab, @@NESTLEVEL-1)
ELSE ''
END)+
'</'+@key+'>';
--- And again, error checks:
---
--- 1. If these are multiple values, the next character
--- should be a comma:
IF (@array=0 AND @json!='' AND LEFT(@json, 1)!=',')
RETURN @output+'Expected "," after value, found "'+
LEFT(@json, 1)+'"!';
--- 2. .. or, if this is an array, the next character
--- should be a comma or a closing angle bracket:
IF (@array=1 AND LEFT(@json, 1) NOT IN (',', ']'))
RETURN @output+'In array, expected "]" or "," after '+
'value, found "'+LEFT(@json, 1)+'"!';
--- If this is where the array is closed (i.e. if it's a
--- closing angle bracket)..
IF (@array=1 AND LEFT(@json, 1)=']') BEGIN;
SET @array=NULL;
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json)));
--- After a closed array, there should be a comma:
IF (LEFT(@json, 1) NOT IN ('', ',')) BEGIN
RETURN 'Closed array, expected ","!';
END;
END;
SET @json=LTRIM(SUBSTRING(@json, 2, LEN(@json)+1));
IF (@array=0) SET @array=NULL;
END;
END;
--- Return the output:
RETURN CAST(@output AS xml);
END;
DECLARE @json varchar(max);
SET @json='{
"Person": {
"firstName": "John",
"lastName": "Smith",
"age": [25, 26, 27],
"Address": {
"streetAddress":"21, 2nd Street",
"city" :"New York",
"state":"NY",
"postalCode":"10021"
},
"PhoneNumbers": {
"home":"212 555-1234",
"fax":"646 555-4567"
}
}
}';
SELECT dbo.fn_parse_json2xml(@json);
发布于 2018-10-22 00:10:37
这个答案真的很晚,可能对你来说太晚了,但它可能对其他人有帮助:
假设结构始终相同,您可以相当容易地将字符串转换为XML:
DECLARE @jsonString NVARCHAR(MAX)=
N'[{"Id":1725,"Number":"12345","qty":1,"Block":true},
{"Id":125,"Number":"1234544","qty":1,"Block":true}]';
DECLARE @Converted XML=
CAST(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(@jsonString,'[','')
,'{"Id":','<row><Id>')
,',"Number":','</Id><Number>')
,',"qty":','</Number><qty>')
,',"Block":','</qty><Block>')
,'},','</Block></row>')
,'}]','</Block></row>') AS XML);
--查看结果
SELECT @Converted;
<row>
<Id>1725</Id>
<Number>"12345"</Number>
<qty>1</qty>
<Block>true</Block>
</row>
<row>
<Id>125</Id>
<Number>"1234544"</Number>
<qty>1</qty>
<Block>true</Block>
</row>
--此XML可以是如下所示的查询:
SELECT a.value('(Id/text())[1]','int') AS Id
,a.value('(Number/text())[1]','nvarchar(max)') AS Number
,a.value('(qty/text())[1]','int') AS qty
,a.value('(Block/text())[1]','bit') AS Block
FROM @Converted.nodes('/row') A(a);
最终结果
Id Number qty Block
1725 "12345" 1 1
125 "1234544" 1 1
https://stackoverflow.com/questions/50658455
复制相似问题