繁体   English   中英

读取嵌套记录列表时出现 ClassCastException

[英]ClassCastException when reading nested list of records

我正在读取来自 Dataflow 的 BigQuery 表,其中一个字段是“记录”和“重复”字段。 所以我希望 Java 中的结果数据类型是List<TableRow>

但是,当我尝试遍历列表时,出现以下异常:

java.lang.ClassCastException: java.util.LinkedHashMap 无法转换为 com.google.api.services.bigquery.model.TableRow

表架构看起来像这样:

{
    "id": "my_id",
    "values": [
        {
            "nested_record": "nested"
        }
    ]
}

迭代值的代码如下所示:

String id = (String) row.get("id");
List<TableRow> values = (List<TableRow>) row.get("values");

for (TableRow nested : values) {
    // more  logic
}

异常在循环开始的地方抛出。 这里明显的解决方法是将值转换为LinkedHashMaps列表,但感觉不对。

为什么 Dataflow 会为嵌套的“记录”抛出这种错误?

当我尝试使用谷歌云数据流从 BigQuery 读取嵌套表时,我遇到了同样的ClassCastException 最后通过将TableRow转换为不同的数据结构来解决,具体取决于我使用的 DataFlow 运行程序:

  • 如果使用DirectRunner :投射到LinkedHashMap
  • 如果使用DataflowRunner :转换为TableRow

例子:

Object valuesList = row.get("values");
// DirectRunner
for (TableRow v : (List<LinkedHashMap>) valuesList) {
   String name = v.get("name");
   String age = v.get("age");
}

// DataflowRunner
for (TableRow v : (List<TableRow>) valuesList) {
   String name = v.get("name");
   String age = v.get("age");
}

看看BEAM-2767

其根本原因是 DirectRunner 在步骤之间执行的编码往返,这通常不会在 Dataflow 中执行。 作为 Map 字段访问重复记录(或任何记录)将在这两个运行器上成功执行,因为 TableRow 实现了 Map 接口。 记录被读取为“TableRow”类型,但是当它们被编码时,它们被编码为一个简单的 JSON 映射。 由于 JSON 编码器无法识别地图字段的类型,因此它将记录反序列化为简单的地图类型。

TableRow 是一个 Map,因此您可以将这两种情况都视为 Map:

    String id = (String) row.get("id");
    List<? extends Map> values = row.get("values");

    for (Map nested : values) {
        // more  logic
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM