Azure 数据工厂从嵌套在 json 中的 json 字符串复制数据
Azure Data Factory copy data from json string nested in a json
我正在从第三方 API 获取数据,后者以 JSON 负载响应。但是,此 JSON 包含另一个 JSON 对象,存储为包含转义字符的字符串。示例:
{
"aggregationType": "IDENTITY",
"outputs": [
{
"name": "Sinusoid|Sinusoid"
}
],
"value": "{\"dataX\":[1,2,3,4],\"dataY\":[1,4,9,16]}"
}
在文件的第一部分,我们有一些常规参数,如'aggregationType'和'outputs',但最后一个参数'value'是我的JSON对象谈论.
我想做的是将 'dataX' 和 'dataY' 数组一起输入到 SQL 数据库上的 table 中。到目前为止,我还没有找到一种直接的方法。
我尝试过的:
- 使用简单的副本 activity,但我只能访问整个 'value' 字段,不能从 'dataY' 中分离出 'dataX',更不用说数组的各个值了.
- 使用查找 activity 然后将 'value' 存储在变量中。从这里我可以在 ADF 中找到可用的 JSON 对象,但我发现将数据发送到数据库的唯一方法是使用包含副本 [=41= 的 ForEach activity ].由于 dataX 和 dataY 实际上要大得多,因此在我调试时这似乎要花很长时间。
- 仅将 'value' 对象复制到 blob 并尝试从那里检索数据。这没有用,因为对象总是以初始 " 标记和 \ 转义字符存储。
有什么办法可以解决这个问题吗?
您可以将值存储在 SQL 中 table 的暂存类型中,然后创建存储过程以将对象分离为数组
JSON_Value可以帮你提取值:
SELECT JSON_VALUE('{"dataX": [1,2,3,4]}', '$.dataX') AS 'Output';
在您的存储过程中,您可以尝试使用上述查询并在 SQL table
中插入值
根据@Pratik Somaiya 的提示,我编写了一个存储过程,用于将数据插入到持久性 table。
我不得不使用 WHILE 循环,但感觉不太对,所以我仍在寻找更好的解决方案。
CREATE OR ALTER PROCEDURE dataset_outputs_from_adf
@json_output_value NVARCHAR(MAX),
@output_name NVARCHAR(100)
AS
DECLARE @i INT = 0
WHILE JSON_VALUE(@json_output_value,CONCAT('$.dataX[',@i,']')) IS NOT NULL
BEGIN
INSERT INTO my_table
VALUES (
@output_name,
JSON_VALUE(
@json_output_value,
CONCAT('$.dataX[',@i,']')
),
JSON_VALUE(
@json_output_value,
CONCAT('$.dataY[',@i,']')
)
)
SET @i = @i + 1
END
GO
通过使用输出名称参数化数据工厂,我应该能够在没有重复代码的情况下使整个事情重复table。
据我了解,您可以检索嵌入的“值”JSON,但它保留了转义字符。您希望将数组 [1,2,3,4]
和 [1,4,9,16]
传递到关系数据库(Microsoft SQL 服务器?)以存储它们。
可以使用表达式 json() 将嵌入的“值”转换为可引用的 JSON。这会处理转义字符。
@json(variables('payload')).dataX
将return数组[1,2,3,4]
如预期。
如何最好地将其放入 SQL 服务器?我们仅限于 ADF 支持的活动,这实际上归结为存储过程 (SP)。使用 table valued parameter 是理想的,但在当前的 ADF 中是不可能的。所以我建议将它作为字符串传递给 SP。
@string(json(variables('payload')).dataX)
这看起来和上面的很像,但是是 string 而不是 array.
在 SP 中有几种方法可以解析此字符串。如果你的版本支持STRING_SPLIT就方便了。请注意,传递的字符串将保留其前导和尾随方括号。这些可以在 ADF 或 SQL 中删除,位置无关紧要。
由于数据是 JSON,因此使用 OPENJSON 可能更有意义。假设我们将 dataX 的内容传递给 SP 参数 @dataX varchar(4000)
。在 SP 里面我们写
create procedure dbo.HandleData
@dataX varchar(4000),
@dataY varchar(4000)
as
insert dbo.SomeTable(ColumnX, ColumnY)
select x.value, y.value
from OPENJSON(@dataX) x
inner join OPENJSON(@dataY) y
on y.[key] = x.[key];
如果数组可能具有不同的长度,或者存在 NULL,或 non-integer 值等,则可能需要更多代码。当然,来自 OPENJSON 的结果集可用于连接或SP 内的任何其他目的。
如果原始有效负载中的 dataX 和 dataY 最终都在同一个 DB 中 table SP 可以被调用两次,每个调用一次。或者,您可以 union 他们在 ADF 中的数组并调用 SP 一次。
我正在从第三方 API 获取数据,后者以 JSON 负载响应。但是,此 JSON 包含另一个 JSON 对象,存储为包含转义字符的字符串。示例:
{
"aggregationType": "IDENTITY",
"outputs": [
{
"name": "Sinusoid|Sinusoid"
}
],
"value": "{\"dataX\":[1,2,3,4],\"dataY\":[1,4,9,16]}"
}
在文件的第一部分,我们有一些常规参数,如'aggregationType'和'outputs',但最后一个参数'value'是我的JSON对象谈论.
我想做的是将 'dataX' 和 'dataY' 数组一起输入到 SQL 数据库上的 table 中。到目前为止,我还没有找到一种直接的方法。
我尝试过的:
- 使用简单的副本 activity,但我只能访问整个 'value' 字段,不能从 'dataY' 中分离出 'dataX',更不用说数组的各个值了.
- 使用查找 activity 然后将 'value' 存储在变量中。从这里我可以在 ADF 中找到可用的 JSON 对象,但我发现将数据发送到数据库的唯一方法是使用包含副本 [=41= 的 ForEach activity ].由于 dataX 和 dataY 实际上要大得多,因此在我调试时这似乎要花很长时间。
- 仅将 'value' 对象复制到 blob 并尝试从那里检索数据。这没有用,因为对象总是以初始 " 标记和 \ 转义字符存储。
有什么办法可以解决这个问题吗?
您可以将值存储在 SQL 中 table 的暂存类型中,然后创建存储过程以将对象分离为数组
JSON_Value可以帮你提取值:
SELECT JSON_VALUE('{"dataX": [1,2,3,4]}', '$.dataX') AS 'Output';
在您的存储过程中,您可以尝试使用上述查询并在 SQL table
中插入值根据@Pratik Somaiya 的提示,我编写了一个存储过程,用于将数据插入到持久性 table。
我不得不使用 WHILE 循环,但感觉不太对,所以我仍在寻找更好的解决方案。
CREATE OR ALTER PROCEDURE dataset_outputs_from_adf
@json_output_value NVARCHAR(MAX),
@output_name NVARCHAR(100)
AS
DECLARE @i INT = 0
WHILE JSON_VALUE(@json_output_value,CONCAT('$.dataX[',@i,']')) IS NOT NULL
BEGIN
INSERT INTO my_table
VALUES (
@output_name,
JSON_VALUE(
@json_output_value,
CONCAT('$.dataX[',@i,']')
),
JSON_VALUE(
@json_output_value,
CONCAT('$.dataY[',@i,']')
)
)
SET @i = @i + 1
END
GO
通过使用输出名称参数化数据工厂,我应该能够在没有重复代码的情况下使整个事情重复table。
据我了解,您可以检索嵌入的“值”JSON,但它保留了转义字符。您希望将数组 [1,2,3,4]
和 [1,4,9,16]
传递到关系数据库(Microsoft SQL 服务器?)以存储它们。
可以使用表达式 json() 将嵌入的“值”转换为可引用的 JSON。这会处理转义字符。
@json(variables('payload')).dataX
将return数组[1,2,3,4]
如预期。
如何最好地将其放入 SQL 服务器?我们仅限于 ADF 支持的活动,这实际上归结为存储过程 (SP)。使用 table valued parameter 是理想的,但在当前的 ADF 中是不可能的。所以我建议将它作为字符串传递给 SP。
@string(json(variables('payload')).dataX)
这看起来和上面的很像,但是是 string 而不是 array.
在 SP 中有几种方法可以解析此字符串。如果你的版本支持STRING_SPLIT就方便了。请注意,传递的字符串将保留其前导和尾随方括号。这些可以在 ADF 或 SQL 中删除,位置无关紧要。
由于数据是 JSON,因此使用 OPENJSON 可能更有意义。假设我们将 dataX 的内容传递给 SP 参数 @dataX varchar(4000)
。在 SP 里面我们写
create procedure dbo.HandleData
@dataX varchar(4000),
@dataY varchar(4000)
as
insert dbo.SomeTable(ColumnX, ColumnY)
select x.value, y.value
from OPENJSON(@dataX) x
inner join OPENJSON(@dataY) y
on y.[key] = x.[key];
如果数组可能具有不同的长度,或者存在 NULL,或 non-integer 值等,则可能需要更多代码。当然,来自 OPENJSON 的结果集可用于连接或SP 内的任何其他目的。
如果原始有效负载中的 dataX 和 dataY 最终都在同一个 DB 中 table SP 可以被调用两次,每个调用一次。或者,您可以 union 他们在 ADF 中的数组并调用 SP 一次。