簡體   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