code: def _serialize(data):
      """In client mode, PerspectiveWidget will normalize the data before
      passing it to the front-end.
  
      Widget comms use a custom serializer and messages are not manually
      serialized to JSON by the user, so take special care to remove certain
      unparsable values such as `datetime.date`."""
      if isinstance(data, list):
          # Check if any values are `datetime.date`
          for row in data:
              if not isinstance(row, dict):
                  raise PerspectiveError(
                      "Received {} in list dataset, expected `dict`!".format(
                          type(row)
                      )
                  )
  
              for k in row.keys():
                  if type(row[k]) is datetime:
                      row[k] = row[k].strftime("%Y-%m-%d %H:%M:%S.%f")
                  elif type(row[k]) is date:
                      row[k] = row[k].strftime("%Y-%m-%d")
          return data
      elif isinstance(data, dict):
          formatted = data
  
          for v in data.values():
              if isinstance(v, type):
                  # serialize schema values to string
                  return {
                      column_name: _type_to_string(data[column_name])
                      for column_name in data
                  }
              elif isinstance(v, numpy.ndarray):
                  # Convert dicts of numpy arrays to dicts of lists
                  formatted = {
                      column_name: data[column_name].tolist()
                      for column_name in data
                  }
                  break
  
          for column_name in formatted.keys():
              # Replace `datetime.datetime` and `datetime.date` with string
              formatted[column_name] = _serialize_datetime(
                  formatted[column_name]
              )
  
          return formatted
      elif isinstance(data, numpy.ndarray):
          # structured or record array
          if not isinstance(data.dtype.names, tuple):
              raise NotImplementedError(
                  "Data should be dict of numpy.ndarray or a structured array."
              )
  
          columns = [data[col].tolist() for col in data.dtype.names]
          formatted = dict(zip(data.dtype.names, columns))
  
          for column_name in formatted.keys():
              # Replace `datetime.datetime` and `datetime.date` with string
              formatted[column_name] = _serialize_datetime(
                  formatted[column_name]
              )
  
          return formatted
      elif isinstance(data, pandas.DataFrame) or isinstance(
          data, pandas.Series
      ):
          # Take flattened dataframe and make it serializable
          d = {}
  
          for name in data.columns:
              column = data[name]
              values = column.values
  
              # Timezone-aware datetime64 dtypes throw an exception when using
              # `numpy.issubdtype` - match strings here instead.
              str_dtype = str(column.dtype)
              if "datetime64" in str_dtype:
                  # Convert all datetimes to string for serializing
                  d[name] = column.dt.strftime(
                      "%Y-%m-%d %H:%M:%S"
                  ).tolist()
              elif str_dtype == "object":
                  # Replace `datetime.datetime` and `datetime.date` with string
                  d[name] = _serialize_datetime(values)
              else:
                  d[name] = values.tolist()
          return d
      else:
          raise NotImplementedError(
              "Cannot serialize a dataset of `{0}`.".format(
                  str(type(data))
              )
          )
  
imports: import base64
  import jinja2
  import json
  import os
  from datetime import date, datetime
  from functools import partial
  import numpy
  import pandas
  from ipywidgets import DOMWidget
  from traitlets import Unicode, observe
  from ..core._version import __version__
  from ..core.data import deconstruct_pandas
  from ..core.exception import PerspectiveError
  from ..libpsp import is_libpsp
  from ..viewer import PerspectiveViewer
label_desc: Use image node_id 3 for calling a global function with example usage: _serialize(data) and returns: data, formatted, formatted, unknown, d