Jolt 数据转换:如何对 JSON 对象中的数值进行求和并添加新字段

Jolt 数据转换:如何对 JSON 对象中的数值进行求和并添加新字段

本教程详细介绍了如何使用 Jolt 对 json 对象中的数值进行求和,并将结果添加为一个新的字段。文章通过分步解析 Jolt 转换规范,演示了如何利用 shift 操作重塑数据结构,并结合 modify-overwrite-beta 操作中的 intSum 函数实现数值累加,最终得到所需的数据输出。

问题描述

在处理 JSON 数据时,我们经常需要对某个对象中的所有数值进行汇总,并将汇总结果作为新的字段添加到输出中。例如,给定以下输入 JSON:

{   "accounts": {     "canara": 1,     "sbi": 0,     "axis": 1,     "hdfc": 0   } }

我们的目标是计算 accounts 对象中所有账户的数值之和(即 1 + 0 + 1 + 0 = 2),并将结果以 “total accounts”: 2 的形式添加到输出中,同时保留原始的账户信息。期望的输出如下:

{   "canara": 1,   "sbi": 0,   "axis": 1,   "hdfc": 0,   "total accounts": 2 }

接下来,我们将详细介绍如何使用 Jolt 来实现这一转换。

Jolt 转换实现

为了实现上述目标,我们需要设计一个包含三个操作步骤的 Jolt 转换规范:

步骤一:数据准备与扁平化 (shift 操作)

第一个 shift 操作的目的是将 accounts 对象中的所有键值对提升到根级别,并同时将所有账户的数值收集到一个临时数组中,以便后续进行求和。

{   "operation": "shift",   "spec": {     "accounts": {       "*": [         ".&",         "accountsAccumulator"       ]     }   } }

解析:

  • “accounts”:匹配输入 JSON 中的 accounts 字段。
  • “*”:匹配 accounts 对象下的所有键(如 canara, sbi 等)。
  • [“.&”, “accountsAccumulator”]:这是一个数组,表示对每个匹配到的键值对执行两种映射:
    • “.&”:将当前匹配到的值(例如 1)映射到当前匹配到的键名(例如 canara)。这会将 {“canara”: 1}、{“sbi”: 0} 等直接提升到输出的根级别。
    • “accountsAccumulator”:将当前匹配到的值(例如 1)收集到一个名为 accountsAccumulator 的数组中。由于 Jolt 默认会将相同路径的多次映射聚合为数组,所以最终 accountsAccumulator 将包含 [1, 0, 1, 0]。

经过此步骤后,中间输出将类似于:

{   "canara": 1,   "sbi": 0,   "axis": 1,   "hdfc": 0,   "accountsAccumulator": [1, 0, 1, 0] }

步骤二:执行求和计算 (modify-overwrite-beta 操作)

第二个操作是 modify-overwrite-beta,它用于执行数据计算和修改。我们将利用其内置的 intSum 函数来计算 accountsAccumulator 数组的总和。

{   "operation": "modify-overwrite-beta",   "spec": {     "total accounts": "=intSum(@(1,accountsAccumulator))"   } }

解析:

  • “total accounts”:指定要创建的新字段名称。
  • “=intSum(@(1,accountsAccumulator))”:
    • =:表示这是一个函数调用。
    • intSum(…):Jolt 内置的整数求和函数。
    • @(1,accountsAccumulator):这是一个相对路径表达式。
      • @:表示引用当前操作输入中的值。
      • 1:表示向上回溯一级(从当前 modify 操作的上下文,即根级别)。
      • accountsAccumulator:指定要引用的字段名。 因此,@(1,accountsAccumulator) 引用的是上一步生成的 accountsAccumulator 数组 [1, 0, 1, 0]。intSum 函数将对这个数组进行求和,结果为 2。

经过此步骤后,中间输出将变为:

{   "canara": 1,   "sbi": 0,   "axis": 1,   "hdfc": 0,   "accountsAccumulator": [1, 0, 1, 0],   "total accounts": 2 }

步骤三:结果整理与输出 (shift 操作)

最后一个 shift 操作的目的是清理临时字段 accountsAccumulator,并确保最终输出的结构符合要求。

{   "operation": "shift",   "spec": {     "accountsAccumulator": NULL,     "*": "&"   } }

解析:

  • “accountsAccumulator”: null:将 accountsAccumulator 字段映射到 null,这在 shift 操作中等同于删除该字段,因为它不会被映射到输出中。
  • “*”: “&”:这是一个通配符映射。它表示将输入中所有其他字段(除了已经被显式处理的 accountsAccumulator)按原样复制到输出中。& 表示将当前匹配到的键名作为输出的键名,其对应的值作为输出的值。这确保了 canara、sbi、axis、hdfc 和 total accounts 等字段被保留并输出。

最终,我们将得到预期的输出:

{   "canara": 1,   "sbi": 0,   "axis": 1,   "hdfc": 0,   "total accounts": 2 }

完整 Jolt 转换规范

将上述三个操作合并,完整的 Jolt 转换规范如下:

[   {     "operation": "shift",     "spec": {       "accounts": {         "*": [           ".&",           "accountsAccumulator"         ]       }     }   },   {     "operation": "modify-overwrite-beta",     "spec": {       "total accounts": "=intSum(@(1,accountsAccumulator))"     }   },   {     "operation": "shift",     "spec": {       "accountsAccumulator": null,       "*": "&"     }   } ]

核心概念与注意事项

  1. 多阶段转换链: 复杂的 Jolt 转换通常需要通过链式组合多个操作来完成。每个操作的输出作为下一个操作的输入,逐步实现数据转换目标。本例中,shift 用于重塑和准备数据,modify-overwrite-beta 用于计算,最后的 shift 用于清理和最终结构化。
  2. shift 操作的灵活性:
    • & 和 .:在 shift 操作中,& 代表当前匹配的键名,. 代表当前匹配的值。它们是构建输出路径和值的重要工具
    • 数组输出:当多个输入路径映射到相同的输出路径时,Jolt 会自动将这些值聚合为一个 JSON 数组。这在收集数据(如本例中的 accountsAccumulator)时非常有用。
  3. modify-overwrite-beta 与数学函数:
    • modify-overwrite-beta 操作是 Jolt 中执行数据计算和修改的核心。它支持多种内置函数,包括数学函数(如 intSum、doubleSum、min、max、abs 等)、字符串函数、逻辑函数等。
    • =functionName(…):这是在 modify 操作中调用 Jolt 函数的语法。
    • @(level, fieldName):这种语法允许您在 modify 操作中引用输入 JSON 中的特定字段,即使该字段不在当前处理的上下文中。level 指示向上回溯的层级。

总结

通过本教程,我们学习了如何使用 Jolt 的 shift 和 modify-overwrite-beta 操作来对 JSON 对象中的数值进行求和,并将结果作为一个新字段添加。这种多阶段的转换方法在 Jolt 中非常常见,能够帮助我们灵活地处理各种复杂的数据转换需求。理解每个操作的职责以及 Jolt 路径表达式和内置函数的使用是掌握 Jolt 转换的关键。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享