【问题标题】:Converting dynamic JSON into a format suitable for loading into Snowflake/relational database将动态 JSON 转换为适合加载到雪花/关系数据库的格式
【发布时间】:2021-09-01 11:32:47
【问题描述】:

我在 API 数据摄取方面的经验有限,并且我们遇到了 API JSON 响应本质上是动态的问题,在 JSON 中包含用于多个元素的数组。如果您不知道将遇到的元素甚至多个值,然后转换为可以轻松加载到 Snowflake 或任何其他关系数据库中的格式,您如何处理动态 JSON?我们尝试将整个 JSON 行转换为单行,但是我们不知道如何为同一列 (ABC) 解析多列 (ABC0、ABC1)。

"Job_Profile_Reference": {
      "ID": [
      {
        "@type": "WI",
        "__text": "4acf03b2e8e301fab3caeab105020f"
      },
      {
        "@type": "Job_Profile_ID",
        "__text": "112"
      }
      ]
    }

输出

Job_Profile.Job_Profile_Reference.ID.0.@type,Job_Profile.Job_Profile_Reference.ID.0.__text,Job_Profile.Job_Profile_Reference.ID.1.@type,Job_Profile.Job_Profile_Reference.ID.1.__text
WI,4acf03b2e8e301fab3caeab105020f,Job_Profile_ID,112

【问题讨论】:

  • 你有没有考虑将JSON直接加载到Snowflake并直接查询?您可以使用 Snowflake SQL 解析您需要的内容,甚至可以创建专门构建的视图。在您上面的示例中,这只是 JSON 的一条记录,还是您的所有记录都是该“ID”数组的一部分?
  • 我们可以,但我们使用 azure 作为我们的数据湖,并希望将 JSON 非规范化为 CSV,以便不仅用于 Snowflake,还用于其他下游应用程序。
  • 这对 Snowflake 来说似乎不是问题——因为您想在加载到 Snowflake 之前完成所有这些操作。尝试将问题转发给jq,他们会帮助您转换 json。
  • 如果您需要 jq 社区的帮助,最好遵循minimal reproducible example 指南。特别是,查看至少一个有效 JSON 样本以及每个样本对应的所需输出会很有帮助。

标签: json dynamic snowflake-cloud-data-platform jq relational


【解决方案1】:

动态 JSON 可以按原样轻松加载到 Snowflake 中。在您的示例中,对于可变长度数组,您可以使用 FLATTEN() 将单行 JSON 分解为查询中的多行。在这种情况下,我建议您也将其作为 JSON 保留在数据湖中。

此类事情的惩罚相对较低,因为 JSON 数据不只是存储为长字符串;取而代之的是,Snowflake 在内部分析加载的 JSON,并采取措施帮助快速查询,例如为您的示例中的 $.Job_Profile_Reference$.Job_Profile_Reference.ID 等频繁路径创建虚拟列。

with semistructured as (select parse_json('{"Job_Profile_Reference": {"ID": [{"@type": "WI","__text": "4acf03b2e8e301fab3caeab105020f"},{"@type": "Job_Profile_ID","__text": "112"}]}}') json)
select * from semistructured, lateral flatten(json, recursive=>True) structured;

JSON    SEQ KEY PATH    INDEX   VALUE   THIS
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   Job_Profile_Reference   Job_Profile_Reference       {    "ID": [      {        "@type": "WI",        "__text": "4acf03b2e8e301fab3caeab105020f"      },      {        "@type": "Job_Profile_ID",        "__text": "112"      }    ]  }  {    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   ID  Job_Profile_Reference.ID        [    {      "@type": "WI",      "__text": "4acf03b2e8e301fab3caeab105020f"    },    {      "@type": "Job_Profile_ID",      "__text": "112"    }  ]  {    "ID": [      {        "@type": "WI",        "__text": "4acf03b2e8e301fab3caeab105020f"      },      {        "@type": "Job_Profile_ID",        "__text": "112"      }    ]  }
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1       Job_Profile_Reference.ID[0] 0   {    "@type": "WI",    "__text": "4acf03b2e8e301fab3caeab105020f"  }    [    {      "@type": "WI",      "__text": "4acf03b2e8e301fab3caeab105020f"    },    {      "@type": "Job_Profile_ID",      "__text": "112"    }  ]
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   @type   Job_Profile_Reference.ID[0]['@type']        "WI"    {    "@type": "WI",    "__text": "4acf03b2e8e301fab3caeab105020f"  }
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   __text  Job_Profile_Reference.ID[0].__text      "4acf03b2e8e301fab3caeab105020f"    {    "@type": "WI",    "__text": "4acf03b2e8e301fab3caeab105020f"  }
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1       Job_Profile_Reference.ID[1] 1   {    "@type": "Job_Profile_ID",    "__text": "112"  }   [    {      "@type": "WI",      "__text": "4acf03b2e8e301fab3caeab105020f"    },    {      "@type": "Job_Profile_ID",      "__text": "112"    }  ]
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   @type   Job_Profile_Reference.ID[1]['@type']        "Job_Profile_ID"    {    "@type": "Job_Profile_ID",    "__text": "112"  }
{    "Job_Profile_Reference": {      "ID": [        {          "@type": "WI",          "__text": "4acf03b2e8e301fab3caeab105020f"        },        {          "@type": "Job_Profile_ID",          "__text": "112"        }      ]    }  }   1   __text  Job_Profile_Reference.ID[1].__text      "112"   {    "@type": "Job_Profile_ID",    "__text": "112"  }```

【讨论】:

  • 将 JSON 保留在 Data Lake 中的问题在于,其他消费应用程序/用户必须将其转换为关系格式。而且,今天我们使用的是雪花,这是我们可以使用变体数据类型的地方,但谁知道明天,我们可能最终会使用其他东西,这就是为什么我们只想避免这条路线。
猜你喜欢
  • 2021-04-12
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 2020-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
相关资源
最近更新 更多