def from_json(self, json):
        """
        convert a json string and return a SchemaDocument
        """
        def _convert_to_python(doc, struct, path="", root_path=""):
            for key in struct:
                if type(key) is type:
                    new_key = '$%s' % key.__name__
                else:
                    new_key = key
                new_path = ".".join([path, new_key]).strip('.')
                if isinstance(struct[key], dict):
                    if doc:  # we don't need to process an empty doc
                        if key in doc:  # we don't care about missing fields
                            _convert_to_python(doc[key], struct[key], new_path, root_path)
                elif type(struct[key]) is list:
                    if struct[key]:
                        if struct[key][0] is datetime.datetime:
                            l_objs = []
                            for obj in doc[key]:
                                obj = fromtimestamp(obj)
                                l_objs.append(obj)
                            doc[key] = l_objs
                        elif isinstance(struct[key][0], R):
                            l_objs = []
                            for obj in doc[key]:
                                db = obj.get('_database') or obj.get('$db')
                                col = obj.get('_collection') or obj.get('$ref')
                                if '_id' in obj:
                                    id_ref = '_id'
                                    if '$oid' in obj['_id']:
                                        obj['_id'] = ObjectId(obj['_id']['$oid'])
                                elif '$id' in obj:
                                    id_ref = '$id'
                                obj_class = struct[key][0]._doc
                                _id = obj[id_ref]
                                obj = getattr(self.connection[db][col], obj_class.__name__).one({'_id': _id})
                                #obj = struct[key][0]._doc(obj, collection=self.connection[db][col]).get_dbref()
                                l_objs.append(obj)
                            doc[key] = l_objs
                        elif isinstance(struct[key][0], dict):
                            if doc[key]:
                                for obj in doc[key]:
                                    _convert_to_python(obj, struct[key][0], new_path, root_path)
                elif struct[key] is datetime.datetime and doc[key] is not None:
                    doc[key] = fromtimestamp(doc[key])
                elif (isinstance(struct[key], R) or isinstance(struct[key],
                                                               DocumentProperties)) and doc[key] is not None:
                    db = doc[key].get('_database') or doc[key].get('$db')
                    col = doc[key].get('_collection') or doc[key].get('$ref')
                    if '_id' in doc[key]:
                        id_ref = '_id'
                    elif '$id' in doc[key]:
                        id_ref = '$id'
                    if '$oid' in doc[key][id_ref]:
                        doc[key][id_ref] = ObjectId(doc[key][id_ref]['$oid'])
                    if isinstance(struct[key], R):
                        obj_class = struct[key]._doc
                    else:
                        obj_class = struct[key]
                    #_id = obj_class(doc[key], collection=self.connection[db][col])[id_ref]
                    _id = doc[key][id_ref]
                    doc[key] = getattr(self.connection[db][col], obj_class.__name__).one({'_id': _id})
        try:
            from json import loads
        except __HOLE__:
            from anyjson import deserialize as loads
        except ImportError:
            raise ImportError("can't import anyjson. Please install it before continuing.")
        obj = loads(json)
        _convert_to_python(obj, self.structure)
        if '_id' in obj:
            if '$oid' in obj['_id']:
                obj['_id'] = ObjectId(obj['_id']['$oid'])
        return self._obj_class(obj, collection=self.collection)

    #
    # End of public API
    #
dataset/ETHPy150Open namlook/mongokit/mongokit/document.py/Document.from_json