We read tables formatted as JSON objects (dicts) here. This is useful when you are reading
        data from a demo. The expected format is::

            {"question": [token1, token2, ...],
             "columns": [column1, column2, ...],
             "cells": [[row1_cell1, row1_cell2, ...],
                       [row2_cell1, row2_cell2, ...],
                       ... ]}

def read_from_json(cls, json_object: Dict[str, Any]) -> 'TableQuestionKnowledgeGraph':
        """
        We read tables formatted as JSON objects (dicts) here. This is useful when you are reading
        data from a demo. The expected format is::

            {"question": [token1, token2, ...],
             "columns": [column1, column2, ...],
             "cells": [[row1_cell1, row1_cell2, ...],
                       [row2_cell1, row2_cell2, ...],
                       ... ]}
        """
        entity_text: Dict[str, str] = {}
        neighbors: DefaultDict[str, List[str]] = defaultdict(list)

        # Getting number entities first.  Number entities don't have any neighbors, and their
        # "entity text" is the text from the question that evoked the number.
        question_tokens = json_object['question']
        for number, number_text in cls._get_numbers_from_tokens(question_tokens):
            entity_text[number] = number_text
            neighbors[number] = []
        for default_number in DEFAULT_NUMBERS:
            if default_number not in neighbors:
                neighbors[default_number] = []
                entity_text[default_number] = default_number

        # Following Sempre's convention for naming columns.  Sempre gives columns unique names when
        # columns normalize to a collision, so we keep track of these.  We do not give cell text
        # unique names, however, as `fb:cell.x` is actually a function that returns all cells that
        # have text that normalizes to "x".
        column_ids = []
        columns: Dict[str, int] = {}
        for column_string in json_object['columns']:
            column_string = column_string.replace('\\n', '\n')
            normalized_string = f'fb:row.row.{cls._normalize_string(column_string)}'
            if normalized_string in columns:
                columns[normalized_string] += 1
                normalized_string = f'{normalized_string}_{columns[normalized_string]}'
            columns[normalized_string] = 1
            column_ids.append(normalized_string)
            entity_text[normalized_string] = column_string

        # Stores cell text to cell name, making sure that unique text maps to a unique name.
        cell_id_mapping: Dict[str, str] = {}
        column_cells: List[List[str]] = [[] for _ in columns]
        for row_index, row_cells in enumerate(json_object['cells']):
            assert len(columns) == len(row_cells), ("Invalid format. Row %d has %d cells, but header has %d"
                                                    " columns" % (row_index, len(row_cells), len(columns)))
            # Following Sempre's convention for naming cells.
            row_cell_ids = []
            for column_index, cell_string in enumerate(row_cells):
                cell_string = cell_string.replace('\\n', '\n')
                column_cells[column_index].append(cell_string)
                if cell_string in cell_id_mapping:
                    normalized_string = cell_id_mapping[cell_string]
                else:
                    base_normalized_string = f'fb:cell.{cls._normalize_string(cell_string)}'
                    normalized_string = base_normalized_string
                    attempt_number = 1
                    while normalized_string in cell_id_mapping.values():
                        attempt_number += 1
                        normalized_string = f"{base_normalized_string}_{attempt_number}"
                    cell_id_mapping[cell_string] = normalized_string
                row_cell_ids.append(normalized_string)
                entity_text[normalized_string] = cell_string
            for column_id, cell_id in zip(column_ids, row_cell_ids):
                neighbors[column_id].append(cell_id)
                neighbors[cell_id].append(column_id)

        for column in column_cells:
            if cls._should_split_column_cells(column):
                for cell_string in column:
                    for part_entity, part_string in cls._get_cell_parts(cell_string):
                        neighbors[part_entity] = []
                        entity_text[part_entity] = part_string
        return cls(set(neighbors.keys()), dict(neighbors), entity_text, question_tokens)