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()
方法中返回该解析器。您不需要执行其他设置。