import json


def PrepareGroupORM(r, obj, mapping, objname, request, mappingattr='mapping'):
    """Prepare data assign to orm

    Examples::
        try:
            r = PrepareGroupORM(r, obj, mapping, obj__heads__, self.args.items())
        except Exception as error:
            return omitError(ErrorMsg=repr(error)), 400

        db.session.merge(r)

    :param sqlalchemy r: The sqlalchemy orm prepares to save.
    :param sqlalchemy obj: The sqlalchemy orm prepares valid that child is exist.
    :param sqlalchemy mapping: The sqlalchemy orm that relationship with r.
    :param Str objname: The second layer that we create one to many, which means
        one group maps many objs.
    :param Dict request: The data reqest from end user want to create.
    :param Str mappingattr: The relationship attribute we want to create.
    :returns: The sqlalchemy ORM if valid.
    :raises: ValueError
    """


    try:
        for k, v in request:
            if v != None :
                if k != objname:
                    setattr(r, k, v)
                else:
                    _mapping = []
                    if isinstance(v, str):
                        v = [v]
                        # when pass one record such as [{"id": "1"}], it could be
                        # deserialized to string type like '{"id": "1"}'
                        # rather than `list` type.

                    for _v in v:
                        objId = json.loads(_v.replace('\'', '"'))['id']

                        if not obj.query.filter(obj.id == objId).scalar():
                        # we make sure atomic
                        # that if one of mapping not found, we exist immediantly.
                            raise ValueError('objId({}) not exist in db'.format(objId))

                        _mapping.append(mapping(objId, r.id))

                    setattr(r, mappingattr, _mapping)

    except Exception as error:
        raise ValueError('deserialize error, error={}'.format(error))

    return r