Java 示例:JSON 解析器

JSON 解析器会使用 JSON 对象流。每个对象都必须具有正确格式,并且必须位于输入中的一行上。可以使用换行符分隔对象。此解析器使用字段名称作为映射中的键,而这些键将成为表中的列名称。可以在 /opt/vertica/packages/flextable/examples 中找到此示例的代码。此目录还包含一个示例数据文件。

此示例使用 setRowFromMap() 方法写入数据。

加载和使用示例

使用第三方库 (gson-2.2.4.jar) 加载库并定义 JSON 解析器,如下所示。有关下载 URL,请参阅 JsonParser.java 中的注释:

=> CREATE LIBRARY json
-> AS '/opt/vertica/packages/flextable/examples/java/output/json.jar'
-> DEPENDS '/opt/vertica/bin/gson-2.2.4.jar' language 'java';
CREATE LIBRARY

=> CREATE PARSER JsonParser AS LANGUAGE 'java'
-> NAME 'com.vertica.flex.JsonParserFactory' LIBRARY json;
CREATE PARSER FUNCTION

您现在可以定义一个表,然后使用 JSON 解析器将数据加载到其中,如下所示:

=> CREATE TABLE mountains(name varchar(64), type varchar(32), height integer);
CREATE TABLE

=> COPY mountains FROM '/opt/vertica/packages/flextable/examples/mountains.json'
-> WITH PARSER JsonParser();
-[ RECORD 1 ]--
Rows Loaded | 2

=> SELECT * from mountains;
-[ RECORD 1 ]--------
name   | Everest
type   | mountain
height | 29029
-[ RECORD 2 ]--------
name   | Mt St Helens
type   | volcano
height |

该数据文件包含一个未加载的值 (hike_safety),因为表定义不包括该列。该数据文件遵循以下格式:

{ "name": "Everest", "type":"mountain", "height": 29029, "hike_safety": 34.1  }
{ "name": "Mt St Helens", "type": "volcano", "hike_safety": 15.4 }

实施

以下代码显示了 JsonParser.java 中的 process() 方法。解析器会尝试将输入读取到一个 Map. 中。如果读取成功,JSON 解析器将调用 setRowFromMap()

    @Override
    public StreamState process(ServerInterface srvInterface, DataBuffer input,
            InputState inputState) throws UdfException, DestroyInvocation {
        clearReject();
        StreamWriter output = getStreamWriter();

        while (input.offset < input.buf.length) {
            ByteBuffer lineBytes = consumeNextLine(input, inputState);

            if (lineBytes == null) {
                return StreamState.INPUT_NEEDED;
            }

            String lineString = StringUtils.newString(lineBytes);

            try {
                Map map = gson.fromJson(lineString, parseType);

                if (map == null) {
                    continue;
                }

                output.setRowFromMap(map);
                // No overrides needed, so just call next() here.
         output.next();
            } catch (Exception ex) {
                setReject(lineString, ex);
                return StreamState.REJECT;
            }
        }

JsonParserFactory.java 工厂会将解析器实例化并在 prepare() 方法中返回该解析器。您不需要执行其他设置。