docs: def _map_value(self, value):
          ''' Maps a raw deserialized row to proper types '''
          # TODO: Once we've gotten here, we've done the following:
          # -> Recieve the full response, copy it from network buffer it into a ByteBuffer (copy 1)
          # -> Copy all the data into a String (copy 2)
          # -> Deserialize that string (copy 3)
          # -> Map the deserialized JSON to our response format (copy 4, what we are doing in this method)
          # This should not bee needed. Technically, this mapping from transport format to python types should require exactly one copy, 
          # from the network buffer into the python VM.
          if isinstance(value, list):
              out = []
              for c in value:
                  out.append(self._map_value( c ))
              return out
          elif isinstance(value, dict) and 'metadata' in value and 'labels' in value['metadata'] and 'self' in value:
              return neo4j.Node(ustr(value['metadata']['id']), value['metadata']['labels'], value['data'])
          elif isinstance(value, dict) and 'metadata' in value and 'type' in value and 'self' in value:
              return neo4j.Relationship(ustr(value['metadata']['id']), value['type'], value['start'].split('/')[-1], value['end'].split('/')[-1], value['data'])
          elif isinstance(value, dict):
              out = {}
              for k,v in value.items():
                  out[k] = self._map_value( v )
              return out
          elif isinstance(value, str):
              return ustr(value)
          else:
              return value