0

I have created a Tableau connector 3 with boilerplate earthquake-data and i try to parse from an api a json file instead of the boilerplate's geojson. The api returns json.

The code below is from the Parser file that i changed.

When i import it to Tableau, it gives me an error that means nonthing.

Unable to complete action

Internal Error - An unexpected error occurred and the operation could not be completed.

Error Code: 0213F756

Is there a way to write a json connector?

What could be wrong? Is there a way to test my code? Can you see a reason why this isn't working?

Any help is appreciated.

import { Parser } from '@tableau/taco-toolkit/handlers'

export default class MyParser extends Parser {
  parse(fetcherResult, { dataContainer }) {

      //  Create a containerBuilder
    const containerBuilder = Parser.createContainerBuilder(dataContainer);

    //  Flatten the JSON query results
    let tables = Object.keys(fetcherResult.data);

    //  Loop through each "key" in the data results
    tables.forEach((tableName) => {

      //  Fetch an array of data for the key
      let originalData = fetcherResult.data[tableName];
     // log(`Parsing data for table: ${tableName}`);

      //  Flatten the data into key-value pairs
      let flattenedData = Object.fromEntries(
          Object.entries(originalData).map(([key, value]) => {
              const generatedKeyValuePairs = [];
              generateNestedKeyNameAndValue(value, "", generatedKeyValuePairs);
              return [key, Object.fromEntries(generatedKeyValuePairs)];
          })
      );
      // Loop through each "row" of data and expand any rows with nested arrays
      let tableDataArrays = []
      for (let rowNumber in Object.keys(flattenedData)){
          tableDataArrays.push(rowSplitter(flattenedData[rowNumber]));
      }
      // That left us with an array of arrays (some w/ 1 row, others with N rows).  Need to flatten once more
      let tableData = tableDataArrays.flat();

      //  Get a reference to this table
      let { isNew, tableBuilder } = containerBuilder.getTable(tableName);

      // Loop over each row in tableData
      let columnsDictionary = {};
      tableData.forEach( row => {
          // Loop over every field in each row (not every row will have the same fields)
          Object.entries(row).map(([fieldname, value]) => {
            // Have we already determined this fields datatype? and does it have a defined dataType? if the datatype is numeric, what if later values are string?
            if (!columnsDictionary[fieldname] || !columnsDictionary[fieldname].dataType || columnsDictionary[fieldname].dataType === DataType.Int || columnsDictionary[fieldname].dataType === DataType.Float){
                // This is a new field, record it's data type
                columnsDictionary[fieldname] = getTableauDatatype(fieldname, value);
            } })})
      // Loop through all the columns
      let columns = [];
      Object.entries(columnsDictionary).map(([columnname, column]) => {
          // Since it's possible that some fields we all null, we need to double check and assign them a default value (string)
          column.dataType = column.dataType ? column.dataType : DataType.String; 
          // Push to the columns array
          columns.push(column);
      })
      //  If this is a new table, add the columns to the tableBuilder
      if (isNew) {
        tableBuilder.addColumnHeaders(columns);
      }
      tableData.map( row => {
        //  Figure out what keys are already existing in the row
        let rowFields = Object.keys(row);
        //  Are any columns missing?
        if (rowFields.length !== columns.length){
          columns.map( column => {
            if (!(column.id in row)){
               if (column.dataType === DataType.Datetime){
                  log('missing datetime value')
                  //row[column.id] = convertDatetimeString(null);
               } else {
                  row[column.id] = null;
               }
            }
          })
        }
      })

      tableBuilder.addRows(tableData);
    })
    return containerBuilder.getDataContainer()
   }
}

0 Answers0