【问题标题】:ClassCastException when reading nested list of records读取嵌套记录列表时发生 ClassCastException
【发布时间】:2019-02-04 15:18:57
【问题描述】:

我正在从 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 会为嵌套的“记录”抛出这种错误?

【问题讨论】:

  • 为什么感觉不对?使用List&lt;LinkedHashMap&gt;(或类似的)实际上是你能做的所有事情(也是正确的事情),因为这是列表中实例的类型。
  • 谢谢@AndyTurner,你有没有链接到某个文档,上面写着“记录”是Java 中的LinkedHashMap。我发现的关于它的 GCP 页面真的很模糊

标签: java google-bigquery google-cloud-dataflow


【解决方案1】:

看看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
    }

【讨论】:

    【解决方案2】:

    当我尝试使用 google cloud 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");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 2020-06-06
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 2015-01-18
      相关资源
      最近更新 更多