【发布时间】:2017-10-04 15:03:29
【问题描述】:
我正在使用来自https://www.red-gate.com/simple-talk/sql/t-sql-programming/producing-json-documents-from-sql-server-queries-via-tsql/ 的例程将存储在表中 XML 列中的 XML 转换为 json(通过 ajax 提供服务)
IF OBJECT_ID (N'dbo.FlattenedJSON') IS NOT NULL
DROP FUNCTION dbo.FlattenedJSON
GO
CREATE FUNCTION dbo.FlattenedJSON (@XMLResult XML)
RETURNS NVARCHAR(MAX)
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE @JSONVersion NVARCHAR(MAX), @Rowcount INT
SELECT @JSONVersion = '', @rowcount=COUNT(*)
FROM @XMLResult.nodes('/root/*') x(a)
SELECT @JSONVersion = @JSONVersion +
STUFF((SELECT TheLine
FROM
(SELECT ',
{'+
STUFF((SELECT ',"'+COALESCE(b.c.value('local-name(.)','NVARCHAR(255)'),'')+'":"'+
REPLACE( --escape tab properly within a value
REPLACE( --escape return properly
REPLACE( --linefeed must be escaped
REPLACE( --backslash too
REPLACE(COALESCE(b.c.value('text()[1]','NVARCHAR(MAX)'),''),--forwardslash
'\', '\\'),
'/', '\/'),
CHAR(10),'\n'),
CHAR(13),'\r'),
CHAR(09),'\t')
+'"'
FROM x.a.nodes('*') b(c)
FOR XML PATH(''),TYPE).value('(./text())
[1]','NVARCHAR(MAX)'),1,1,'')+'}'
FROM @XMLResult.nodes('/root/*') x(a)
) JSON(theLine)
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)' )
,1,1,'')
IF @Rowcount>1 RETURN '['+@JSONVersion+']'
RETURN @JSONVersion
当 XML 是时它工作得很好
<product>
...
<height>123</height>
<width>234</width>
</product>
返回这个结果:
{..."height":"123","width","234"}
但另一个供应商以这种格式提供数据
<product>
<int name="height">123</int>
<int name="width">234</int>
<str name="colour">red</str>
...
</product>
返回这个结果:
{"int":"123","int":"234","str":"red"}
这没什么用。可以为这种格式的 XML 制作类似于上面的例程吗?
有些属性是数组
<arr name="images">
<str>image1.jpg</str>
<str>image2.jpg</str>
<str>image3.jpg</str>
</arr>
但我可以没有这些。
【问题讨论】:
-
如果将第 17 行替换为 STUFF((SELECT ',"'+COALESCE(b.c.value(@name,'NVARCHAR(255)'),'') +'":"'+ etc ... 使用 name 属性?这应该为第二种形式的文档产生所需的输出。仍然不适用于数组版本
-
可能遗漏了一些简单的东西,但我收到了这个错误:必须声明@name。如果我把它放在单引号中,它会编译,但返回 null。
-
您是否考虑过在 SQL 上编写 C# clr 来生成 json?
-
不,如果sql中的一个函数可以做一个转换,那么另一个也应该可以。
标签: sql-server json xml xpath xquery