FJSONPARSER

解析并加载 JSON 文件。此文件可能包含重复的 JSON 数据对象(包括嵌套映射)或 JSON 元素的外部列表。

加载到 Flex 表或混合表中时,解析器将 JSON 数据存储在单值 VMap 中。加载到混合表或列式表中时,解析器将数据直接加载到列名称与 JSON 源数据键相匹配的任何表列。

您可以使用强类型加载 JSON 源(数组、结构或组合)中的复杂类型,或将其作为灵活的复杂类型加载。将灵活的复杂类型加载到 VMap 列中的操作与加载到 Flex 表中一样。要加载复杂类型作为 VMap 列,请将列类型指定为 LONG VARBINARY。要保留复杂类型的索引,请将 flatten_maps 设置为 false。

仅当指定了 record_terminator 时,FJSONPARSER 才支持 协作解析。它不支持分摊加载

语法

FJSONPARSER ( [parameter=value[,...]] )

参数

flatten_maps
布尔值,是否将 JSON 数据中的子映射平展,以句点 (.) 分隔映射层级。此值会影响加载中的所有数据,包括嵌套映射。

此参数仅适用于 Flex 表或 VMap 列,且会在加载强类型复杂类型时被忽略。

默认值:true

flatten_arrays
布尔值,是否将列表转换为带有整数键的子映射。列表被平展后,键名会像映射一样连接起来。默认不对列表进行平展。此值影响加载中的所有数据,包括嵌套列表。

此参数仅适用于 Flex 表或 VMap 列,且会在加载强类型复杂类型时被忽略。

默认值:false

reject_on_duplicate
布尔值,是忽略重复记录 (false),还是拒绝重复记录 (true)。在任何一种情况下,都会继续加载。

默认值:false

reject_on_empty_key
布尔值,是否拒绝包含的字段键不含值的任何行。

默认值:false

omit_empty_keys
布尔值,是否忽略数据中不含值的任何字段键。同一记录中的其他字段将加载。

默认值:false

record_terminator
设置后,将跳过所有无效的 JSON 记录,并继续解析下一个记录。必须统一终止记录。例如,如果您的输入文件包含通过换行符终止的 JSON 记录,请将此参数设置为 E'\n')。如果存在任何无效的 JSON 记录,则在下一个 record_terminator 之后继续解析。

即使数据不包含无效的记录,也可以指定显式记录终止符,这样可以提高协作解析和分摊加载的运行效率,从而提升加载性能。

如果忽略此参数,解析将在第一条无效 JSON 记录处结束。

reject_on_materialized_type_error

布尔值,是否拒绝包含无法强制转换为兼容数据类型的实体化列值的数据行。如果值为 false 且无法强制类型,则解析器将该列中的值设置为 null。

如果该列是强类型复杂类型,而不是可变复杂类型,则复杂类型中的类型不匹配将导致整个列被视为不匹配。解析器不会部分加载复杂类型。

默认值:false

start_point
字符串,即 JSON 加载数据中用作解析起点的键的名称。解析器忽略 start_point 值之前的所有数据。将为文件中的每个对象加载该值。解析器会处理第一个实例后面的数据,最多到第二个,便会忽略任何保留的数据。
start_point_occurrence
整数,您通过 start_point 指定的值的第 n 次出现。如果数据具有多个起始值,而且您知道要在其第几次出现时开始解析,请与 start_point 结合使用。

默认值: 1

suppress_nonalphanumeric_key_chars
布尔值,是否禁止显示 JSON 键值中的非字母数字字符。当此参数为 true 时,解析器将用下划线 (_) 替换这些字符。

默认值:false

key_separator
解析器在连接键名时要使用的字符。

默认: 句点 (.)

示例

以下示例使用默认参数从 STDIN 加载 JSON 数据:

=> CREATE TABLE people(age INT, name VARCHAR);
CREATE TABLE

=> COPY people FROM STDIN PARSER FJSONPARSER();
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> {"age": 5, "name": "Tim"}
>>  {"age": 3}
>>  {"name": "Fred"}
>>  {"name": "Bob", "age": 10}
>> \.
=> SELECT * FROM people;
 age | name
-----+------
     | Fred
  10 | Bob
   5 | Tim
   3 |
(4 rows)

以下示例使用 reject_on_duplicate 参数拒绝重复值:

=> CREATE FLEX TABLE json_dupes();
CREATE TABLE
=> COPY json_dupes FROM stdin PARSER fjsonparser(reject_on_duplicate=true)
exceptions '/home/dbadmin/load_errors/json_e.out'
rejected data '/home/dbadmin/load_errors/json_r.out';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> {"a":"1","a":"2","b":"3"}
>> \.
=>  \!cat /home/dbadmin/load_errors/json_e.out
COPY: Input record 1 has been rejected (Rejected by user-defined parser).
Please see /home/dbadmin/load_errors/json_r.out, record 1 for the rejected record.
COPY: Loaded 0 rows, rejected 1 rows.

以下示例将加载数组数据:

$ cat addrs.json
 {"number": 301, "street": "Grant", "attributes": [1, 2, 3, 4]}

=> CREATE EXTERNAL TABLE customers(number INT, street VARCHAR, attributes ARRAY[INT])
    AS COPY FROM 'addrs.json' PARSER fjsonparser();

=> SELECT number, street, attributes FROM customers;
 num | street| attributes
-----+-----------+---------------
301  | Grant | [1,2,3,4]
(1 row)

以下示例将加载一个灵活的复杂类型,同时拒绝嵌套记录中具有空键的行。请注意,虽然数据包含两家餐厅,但其中一家的键名是空字符串。此餐厅将被拒绝:

$ cat rest1.json
{
    "name" : "Bob's pizzeria",
    "cuisine" : "Italian",
    "location_city" : ["Cambridge", "Pittsburgh"],
    "menu" : [{"item" : "cheese pizza", "" : "$8.25"},
              {"item" : "spinach pizza", "price" : "$10.50"}]
}
{
    "name" : "Bakersfield Tacos",
    "cuisine" : "Mexican",
    "location_city" : ["Pittsburgh"],
    "menu" : [{"item" : "veggie taco", "price" : "$9.95"},
              {"item" : "steak taco", "price" : "$10.95"}]
}

=> CREATE TABLE rest (name VARCHAR, cuisine VARCHAR, location_city LONG VARBINARY, menu LONG VARBINARY);

=> COPY rest FROM '/data/rest1.json'
    PARSER fjsonparser(flatten_maps=false, reject_on_empty_key=true);
Rows Loaded
------------
       1
(1 row)

=> SELECT maptostring(location_city), maptostring(menu) FROM rest;
        maptostring        |                          maptostring
---------------------------+-------------------------------------------------------
 {
    "0": "Pittsburgh"
} | {
    "0": {
        "item": "veggie taco",
        "price": "$9.95"
    },
    "1": {
        "item": "steak taco",
        "price": "$10.95"
    }
}
(1 row)

要改为加载部分数据,请使用 omit_empty_keys 在加载其他所有内容时绕过缺失键:



=> COPY rest FROM '/data/rest1.json'
    PARSER fjsonparser(flatten_maps=false, omit_empty_keys=true);
 Rows Loaded
-------------
           2
(1 row)

=> SELECT maptostring(location_city), maptostring(menu) from rest;
                   maptostring                   |               maptostring
-------------------------------------------------+---------------------------------
 {
    "0": "Pittsburgh"
}                       | {
    "0": {
        "item": "veggie taco",
        "price": "$9.95"
    },
    "1": {
        "item": "steak taco",
        "price": "$10.95"
    }
}
 {
    "0": "Cambridge",
    "1": "Pittsburgh"
} | {
    "0": {
        "item": "cheese pizza"
    },
    "1": {
        "item": "spinach pizza",
        "price": "$10.50"
    }
}
(2 rows)

要改为使用强类型加载此数据,请在表中定义复杂类型:

=> CREATE EXTERNAL TABLE restaurants
  (name VARCHAR, cuisine VARCHAR,
   location_city ARRAY[VARCHAR(80)],
   menu ARRAY[ ROW(item VARCHAR(80), price FLOAT) ]
  )
 AS COPY FROM '/data/rest.json' PARSER fjsonparser();

=> SELECT * FROM restaurants;
       name        | cuisine |       location_city        |                    \
                menu
-------------------+---------+----------------------------+--------------------\
--------------------------------------------------------
 Bob's pizzeria    | Italian | ["Cambridge","Pittsburgh"] | [{"item":"cheese pi\
zza","price":0.0},{"item":"spinach pizza","price":0.0}]
 Bakersfield Tacos | Mexican | ["Pittsburgh"]             | [{"item":"veggie ta\
co","price":0.0},{"item":"steak taco","price":0.0}]
(2 rows)

有关其他示例,请参阅 JSON 数据