Snowflake cloud data platform 从包含不带分隔符的json对象的文件加载数据

Snowflake cloud data platform 从包含不带分隔符的json对象的文件加载数据,snowflake-cloud-data-platform,Snowflake Cloud Data Platform,我正在尝试将s3中的文件中的数据加载到snowflake中。出于我无法控制的原因,这些文件的内容是没有分隔符的JSON对象,例如,单个文件如下所示: {“key1”:“valueA”、“key2”:“valueB”}{“key1”:“valueC”、“key2”:“valueD”} 因此,我无法使用任何分隔符创建文件格式。我想使用}{然后用缺少的括号包装两个记录(JSON对象),但没有这样的选项,记录分隔符接受单个字符。另一种方法可能是使用正则表达式捕获单个记录,但我在文档中看不到任何内容 有没

我正在尝试将s3中的文件中的数据加载到snowflake中。出于我无法控制的原因,这些文件的内容是没有分隔符的JSON对象,例如,单个文件如下所示:
{“key1”:“valueA”、“key2”:“valueB”}{“key1”:“valueC”、“key2”:“valueD”}

因此,我无法使用任何分隔符创建文件格式。我想使用
}{
然后用缺少的括号包装两个记录(JSON对象),但没有这样的选项,记录分隔符接受单个字符。另一种方法可能是使用正则表达式捕获单个记录,但我在文档中看不到任何内容


有没有更好的方法处理这个问题?

因为文件作为一个整体不是有效的JSON,所以不能将其作为半结构化数据读取

如果对象在内部
}
字符处拆分,则可以将文件读取为CSV并稍微聪明地重新组装:

CREATE OR REPLACE TABLE T (
  LINE_NO NUMBER IDENTITY,
  JSON TEXT
);

COPY INTO T(JSON) FROM (SELECT $1||'}' JSON FROM @my_stage/json.csv)
FILE_FORMAT = (TYPE = CSV FIELD_DELIMITER = NONE RECORD_DELIMITER='}');

SELECT REC_NO, PARSE_JSON(LISTAGG(JSON) WITHIN GROUP (ORDER BY LINE_NO)) JSON FROM (
  SELECT
    SUM(CASE WHEN NEW_OBJ AND MOD(QUOTE_QTY_AGG - QUOTE_QTY, 2) = 0 THEN 1 ELSE 0 END)
        OVER (ORDER BY LINE_NO) REC_NO, LINE_NO, JSON
  FROM (
    SELECT
      REGEXP_COUNT(JSON, '"') - REGEXP_COUNT(JSON, '\\\\"') QUOTE_QTY,
      SUM(REGEXP_COUNT(JSON, '"') - REGEXP_COUNT(JSON, '\\\\"'))
          OVER (ORDER BY LINE_NO) QUOTE_QTY_AGG,
      REGEXP_LIKE(JSON, '\\s*\\{\\s*".*') NEW_OBJ,
      LINE_NO, JSON
    FROM T
  )
)
GROUP BY REC_NO
ORDER BY REC_NO;
上面的查询将解析任何“有效”(对多个对象进行模化)JSON,甚至像
{{a}:“{b}}}
这样的对象。它通过观察以下内容来实现:

  • 新对象以
    {“
    开头,但如果
    {
    在字符串中,则不以该开头
  • 如果前几行中未转换的双引号字符数为偶数,则当前行的开头不在字符串内

汉斯的方法可以奏效,但这是一个相当不错的技巧

如果文件不太大(最多几兆字节),有一种更简单的方法

然后,您可以将整个文件作为单个
varchar
值读取,并使用下面的内容对其进行后期处理

  • }{
  • 如果需要,“修复”缺失的卷发
  • parse_json
    结果:
代码如下:

create or replace table x(v varchar) as 
  select * from values('{"a":1}{"b":2}{"c":{"cc":3}}');

select parse_json(
  concat(
    iff(startswith(spl.value,'{'), '', '{'),  -- add '{' if needed 
    spl.value,
    iff(endswith(spl.value, '}'), '', '}')  -- add '}' if needed
  )
) rec 
from x, lateral split_to_table(v, '}{') spl;
-------------+
     REC     |
-------------+
 {           |
   "a": 1    |
 }           |
 {           |
   "b": 2    |
 }           |
 {           |
   "c": {    |
     "cc": 3 |
   }         |
 }           |
-------------+

我同意-这不是JSON。这是一个很好的攻击。但是,当JSON中的字段值包含括号时,它似乎失败了。例如,{“a”:“{”b:“c”}@LouaiGhalia您是对的,尽管您的JSON似乎无效,但引号{U QTY'(\\\.\124;[^]的regexp)*“'不正确。在上面的代码中,我将其替换为两个简单的regexp。我首先将文件作为一行读取,但不能在所有情况下使用Snowflake regexp 100%正确拆分(它们不会回溯)。我在上面修改了我的查询,以便它现在可以处理任何对象,而您必须维护解析状态才能执行此操作。不幸的是,复杂性级别现在非常荒谬。请不要搞错:这不是JSON,您应该确保您的提供方不会因为声称它符合已知标准而逍遥法外: