code: def jsonify(obj):  # pylint: disable=too-many-return-statements
      
      # Call the `to_json` method if available and add metadata.
      if hasattr(obj, 'to_json'):
          d = obj.to_json()
          _push_metadata(d, obj)
          return jsonify(d)
  
      # If we have a numpy array, convert it to a list.
      if isinstance(obj, np.ndarray):
          return obj.tolist()
  
      # If we have NumPy datatypes, convert them to native types.
      if isinstance(obj, (np.int32, np.int64)):
          return int(obj)
      if isinstance(obj, np.float64):
          return float(obj)
  
      # Recurse over dictionaries.
      if isinstance(obj, dict):
          return _jsonify_dict(obj)
  
      # Recurse over object dictionaries.
      if hasattr(obj, '__dict__'):
          return _jsonify_dict(obj.__dict__)
  
      # Recurse over lists and tuples.
      if isinstance(obj, (list, tuple)):
          return [jsonify(item) for item in obj]
  
      # Otherwise, give up and hope it's serializable.
      return obj
docs: Return a JSON-encodable representation of an object, recursively using
      any available ``to_json`` methods, converting NumPy arrays and datatypes to
      native lists and types along the way.