Odoo JsonRPC的参数传递分析 - xiaohao0576/odoo-doc GitHub Wiki

网址入口

https://database_name.odoo.com/jsonrpc

--header 'Content-Type: application/json'

JSON数据格式

{"jsonrpc": "2.0", "method": "call", "params": {"arg1": "val1" }, "id": 123232}

"jsonrpc": "2.0"这个是固定的,不变化

"method": "call",这个也是固定的, method的值odoo会忽略

params,这个key是必须的,很重要,下面会讲具体的格式

id,这个使用随机数字就可以

参考代码: https://github.com/odoo/odoo/blob/62d05a7a942ca344ca8ad02bc27ec58a565cab75/odoo/http.py#L2295

params的格式

    @route('/jsonrpc', type='json', auth="none", save_session=False)
    def jsonrpc(self, service, method, args):
        """ Method used by client APIs to contact OpenERP. """
        _check_request()
        return dispatch_rpc(service, method, args)

根据上面的代码, service, method, args这三个参数是必需要有的,也就是从params数组中提取出来的

其中,service有以下三个取值, common,db,object, 分别对应三个不同的dispatch

    rpc_dispatchers = {
        'common': odoo.service.common.dispatch,
        'db': odoo.service.db.dispatch,
        'object': odoo.service.model.dispatch,
    }

service取值object

当service取值object的时候, method固定为execute_kw, 代码如下

def execute_kw(db, uid, obj, method, args, kw=None):
    return execute(db, uid, obj, method, *args, **kw or {})
  1. 当service取值object的时候, args是一个数组,传递后的参数名称又变成了parms, 前三个位置参数一定是 db, uid, passwd
  2. 第四个参数是 obj的名字,比如res.partner
  3. 第五个参数是obj里面的公开方法,比如read
  4. 第6个参数是一个数组,传递给上面的方法的位置参数,不能省略,就算没有参数,也需要写一个空的列表, []
  5. 第7个参数可选,是一个字典,表示命名参数, 可以传递context,这个context也能在服务器动作中获取
def dispatch(method, params):
    db, uid, passwd = params[0], int(params[1]), params[2]
    security.check(db, uid, passwd)

    threading.current_thread().dbname = db
    threading.current_thread().uid = uid
    registry = Registry(db).check_signaling()
    with registry.manage_changes():
        if method == 'execute':
            res = execute(db, uid, *params[3:])
        elif method == 'execute_kw':
            res = execute_kw(db, uid, *params[3:])
        else:
            raise NameError("Method not available %s" % method)
    return res

参考链接: https://github.com/odoo/odoo/blob/62d05a7a942ca344ca8ad02bc27ec58a565cab75/odoo/service/model.py#L47

最终调用 call_kw函数

def call_kw(model, name, args, kwargs):
    """ Invoke the given method ``name`` on the recordset ``model``. """
    method = getattr(model, name, None)
    if not method:
        raise AttributeError(f"The method '{name}' does not exist on the model '{model._name}'")
    api = getattr(method, '_api', None)

    if api:
        # @api.model, @api.model_create -> no ids
        recs = model
    else:  # 如果方法没有用@api.model , @api.model_create装饰, 就把args第一个参数作为record的ids, 比如下面例子中调用服务器动作的run方法
        ids, args = args[0], args[1:]
        recs = model.browse(ids)

    # altering kwargs is a cause of errors, for instance when retrying a request
    # after a serialization error: the retry is done without context!
    # kwargs里面的context对象,会被单独取出来,作为records的context字典
    kwargs = dict(kwargs)
    context = kwargs.pop('context', None) or {}
    recs = recs.with_context(context)

    _logger.debug("call %s.%s(%s)", recs, method.__name__, Params(args, kwargs))
    result = getattr(recs, name)(*args, **kwargs)
    if api == "model_create":
        # special case for method 'create'
        result = result.id if isinstance(args[0], Mapping) else result.ids
    else:
        result = downgrade(method, result, recs, args, kwargs)

    return result

源码链接: https://github.com/odoo/odoo/blob/7fc2cf32e5f6d1699ed17ef832eec4e9b2679358/odoo/api.py#L514

返回值

如果没有错误,返回值如下 response = {'jsonrpc': '2.0', 'id': self.request_id, 'result':{}}

如果有错误,返回值如下 response = {'jsonrpc': '2.0', 'id': self.request_id, 'error':{}}

参考代码

    def _response(self, result=None, error=None):
        response = {'jsonrpc': '2.0', 'id': self.request_id}
        if error is not None:
            response['error'] = error
        if result is not None:
            response['result'] = result

        return self.request.make_json_response(response)

示例payload

curl --location 'https://database_name.odoo.com/jsonrpc' \
--header 'Content-Type: application/json' \
--data '{
    "jsonrpc": "2.0",
    "method": "call",
    "params": {
        "service": "object",
        "method": "execute_kw",
        "args": [
            "database_name",  
            6,              
            "79a46api_key787dsfs",      
            "ir.actions.server",    
            "run",                  
            [1105](/xiaohao0576/odoo-doc/wiki/1105),
            {"context": {"lang": "zh_CN","chat_id": "777766666"}}  
        ],
        "kwargs": {}
    },
    "id": 12121
}'