docs: def process_decoded(self, d):
          """
          Recursive method to support decoding dicts and lists containing
          pymatgen objects.
          """
          if isinstance(d, dict):
              if "@module" in d and "@class" in d:
                  modname = d["@module"]
                  classname = d["@class"]
              else:
                  modname = None
                  classname = None
              if modname and modname not in ["bson.objectid", "numpy"]:
                  if modname == "datetime" and classname == "datetime":
                      try:
                          dt = datetime.datetime.strptime(d["string"],
                                                          "%Y-%m-%d %H:%M:%S.%f")
                      except ValueError:
                          dt = datetime.datetime.strptime(d["string"],
                                                          "%Y-%m-%d %H:%M:%S")
                      return dt
  
                  mod = __import__(modname, globals(), locals(), [classname], 0)
                  if hasattr(mod, classname):
                      cls_ = getattr(mod, classname)
                      data = {k: v for k, v in d.items()
                             if not k.startswith("@")}
                      if hasattr(cls_, "from_dict"):
                          return cls_.from_dict(data)
              elif np is not None and modname == "numpy" and classname == \
                      "array":
                  return np.array(d["data"], dtype=d["dtype"])
  
              elif (bson is not None) and modname == "bson.objectid" and \
                      classname == "ObjectId":
                  return bson.objectid.ObjectId(d["oid"])
  
              return {self.process_decoded(k): self.process_decoded(v)
                      for k, v in d.items()}
          elif isinstance(d, list):
              return [self.process_decoded(x) for x in d]
  
          return d