docs: private TableRow getTypedTableRow(List<TableFieldSchema> fields, Map<String, Object> rawRow) {
      // If rawRow is a TableRow, use it. If not, create a new one.
      TableRow row;
      List<? extends Map<String, Object>> cells;
      if (rawRow instanceof TableRow) {
        // Since rawRow is a TableRow it already has TableCell objects in setF. We do not need to do
        // any type conversion, but extract the cells for cell-wise processing below.
        row = (TableRow) rawRow;
        cells = row.getF();
        // Clear the cells from the row, so that row.getF() will return null. This matches the
        // behavior of rows produced by the BigQuery export API used on the service.
        row.setF(null);
      } else {
        row = new TableRow();
  
        // Since rawRow is a Map<String, Object> we use Map.get("f") instead of TableRow.getF() to
        // get its cells. Similarly, when rawCell is a Map<String, Object> instead of a TableCell,
        // we will use Map.get("v") instead of TableCell.getV() get its value.
        @SuppressWarnings("unchecked")
        List<? extends Map<String, Object>> rawCells =
            (List<? extends Map<String, Object>>) rawRow.get("f");
        cells = rawCells;
      }
  
      checkState(cells.size() == fields.size(),
          "Expected that the row has the same number of cells %s as fields in the schema %s",
          cells.size(), fields.size());
  
      // Loop through all the fields in the row, normalizing their types with the TableFieldSchema
      // and storing the normalized values by field name in the Map<String, Object> that
      // underlies the TableRow.
      Iterator<? extends Map<String, Object>> cellIt = cells.iterator();
      Iterator<TableFieldSchema> fieldIt = fields.iterator();
      while (cellIt.hasNext()) {
        Map<String, Object> cell = cellIt.next();
        TableFieldSchema fieldSchema = fieldIt.next();
  
        // Convert the object in this cell to the Java type corresponding to its type in the schema.
        Object convertedValue = getTypedCellValue(fieldSchema, cell.get("v"));
  
        String fieldName = fieldSchema.getName();
        checkArgument(!RESERVED_FIELD_NAMES.contains(fieldName),
            "BigQueryIO does not support records with columns named %s", fieldName);
  
        if (convertedValue == null) {
          // BigQuery does not include null values when the export operation (to JSON) is used.
          // To match that behavior, BigQueryTableRowiterator, and the DirectRunner,
          // intentionally omits columns with null values.
          continue;
        }
  
        row.set(fieldName, convertedValue);
      }
      return row;
    }