code: def _ToJSonObj(self, columns_order=None, order_by=()):
      if columns_order is None:
        columns_order = [col["id"] for col in self.__columns]
      col_dict = dict([(col["id"], col) for col in self.__columns])
      col_objs = []
      for col_id in columns_order:
        col_obj = {"id": col_dict[col_id]["id"],
                   "label": col_dict[col_id]["label"],
                   "type": col_dict[col_id]["type"]}
        if col_dict[col_id]["custom_properties"]:
          col_obj["p"] = col_dict[col_id]["custom_properties"]
        col_objs.append(col_obj)
      row_objs = []
      for row, cp in self._PreparedData(order_by):
        cell_objs = []
        for col in columns_order:
          value = self.CoerceValue(row.get(col, None), col_dict[col]["type"])
          if value is None:
            cell_obj = None
          elif isinstance(value, tuple):
            cell_obj = {"v": value[0]}
            if len(value) > 1 and value[1] is not None:
              cell_obj["f"] = value[1]
            if len(value) == 3:
              cell_obj["p"] = value[2]
          else:
            cell_obj = {"v": value}
          cell_objs.append(cell_obj)
        row_obj = {"c": cell_objs}
        if cp:
          row_obj["p"] = cp
        row_objs.append(row_obj)
      json_obj = {"cols": col_objs, "rows": row_objs}
      if self.custom_properties:
        json_obj["p"] = self.custom_properties
      return json_obj