Skip to content

[6769][ADD] endpoint_json2 - #8

Merged
yostashiro merged 16 commits into
19.0from
add-endpoint_json2
Aug 6, 2026
Merged

[6769][ADD] endpoint_json2#8
yostashiro merged 16 commits into
19.0from
add-endpoint_json2

Conversation

@yostashiro

@yostashiro yostashiro commented May 23, 2026

Copy link
Copy Markdown
Member

Adds exec_mode="json2" to the endpoint framework, enabling declarative JSON-2 API
endpoint configuration. Select a model, method, and parameters — the module handles
dispatch, parameter validation, access control, and result filtering. A code snippet
can be used as an alternative to a model method for quick, ad-hoc logic.

Also provides auto-generated API documentation endpoints at /json2/doc.

QT6769

@yostashiro yostashiro changed the title [ADD] endpoint_json2 [6769][ADD] endpoint_json2 May 24, 2026
@yostashiro

Copy link
Copy Markdown
Member Author

There is a usability issue with creating an json2 endpoint which I assume should be cleared by assigning precompute=True to the route field in endpoint_route_handler.

@AungKoKoLin1997 Please check out the issue and create a PR to update endpoint_route_handler as appropriate.

@AungKoKoLin1997 AungKoKoLin1997 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@yostashiro

Copy link
Copy Markdown
Member Author

Pushed [IMP] endpoint_json2: add response language forcing (3604e4b) — optional json2_lang_id forcing the execution context language so translatable values (incl. dotted relational fields) are deterministic per endpoint. Implements IF共通仕様 No.3(日本語で連携); pairs with the dedicated navi API user's lang=ja_JP. HttpCase test included; version kept at 19.0.1.0.0 (unreleased).

@yostashiro
yostashiro force-pushed the add-endpoint_json2 branch 3 times, most recently from 0e5622e to 38f7787 Compare July 26, 2026 09:25
Translatable field values were returned in the API user's language, making
integration payloads dependent on a user setting anyone can change. Add an
optional Response Language (json2_lang_id) that forces the execution context
language, so translated values (including dotted relational fields such as
uom_id.name) are deterministic per endpoint.
@yostashiro
yostashiro force-pushed the add-endpoint_json2 branch from 38f7787 to 1267505 Compare July 26, 2026 09:31
The test setUpClass created its shared endpoint on the same route as the
demo data (/json2/contacts/get_partners), so running the tests against a
database with demo data enabled failed on the endpoint route unique
constraint before any test ran. Move the test endpoints to a test_contacts
route group.
Datetime values were serialized as stored (UTC), forcing every caller to
know and apply the instance timezone. Add an optional Response Timezone
(json2_tz) that converts datetimes in the response to the given timezone,
rendered as local wall time without an offset, and puts the timezone on the
execution context. Incoming datetime parameters are not converted.
@yostashiro

Copy link
Copy Markdown
Member Author

543ca2fadd-endpoint_json2 に push しました(2a4dd8e の Response Timezone を設計変更)。

変更内容: datetime の出力を常に ISO 8601(RFC 3339・UTCオフセット付き) にしました。json2_tz は「どのオフセットで返すか」を選ぶだけの設定になり、オフセットなしのローカル壁時計出力は廃止です。

  • 2a4dd8ejson2_tz 指定時に .replace(tzinfo=None) でオフセットを捨てて %Y-%m-%d %H:%M:%S を返していました。この文字列は Odoo ネイティブのUTC表記と区別できないため、「Odooの日時はUTC」という前提の受信側が無言で9時間ずれて解釈できる状態でした。
  • 変換は fields.Datetime.context_timestamp に置き換え(OCA rest-frameworkpydantic/utils.py と同じ流儀)。自前の pytz 変換とimportは削除。
  • json2_tz 未設定時は UTC を明示的に固定context_timestampenv.tz を解決するため、そのままだと呼び出し元APIユーザのタイムゾーンに追従してしまう潜在バグがありました。

互換性: json2_tz 未設定時の既定出力も変わります(2026-01-15 10:30:002026-01-15T10:30:00+00:00)。同一の時点で自己記述的な形式になりますが、旧形式をパースしている利用側は対応が必要です。

テスト: デモデータ入りDBで 37 tests / 0 failed。既存3アサーションを新形式へ更新し、UTC表記とローカル表記が同一時点にパースされる往復チェックを追加。

 endpoint_json2/README.rst                        |  9 +++++----
 endpoint_json2/models/endpoint_endpoint.py       | 16 ++++++++--------
 endpoint_json2/readme/CONFIGURE.md               | 10 ++++++----
 endpoint_json2/static/description/index.html     |  9 +++++----
 endpoint_json2/tests/test_endpoint_json2.py      |  5 +++--
 endpoint_json2/tests/test_endpoint_json2_controller.py | 19 ++++++++++---------

@yostashiro
yostashiro requested a lite review from Copilot and removed request for SanamiK August 6, 2026 00:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new Odoo addon (endpoint_json2) that extends the existing endpoint framework with exec_mode="json2" to support declarative JSON-2 API endpoints, including parameter validation, access control, response-field filtering/aliasing, and auto-generated documentation at /json2/doc.

Changes:

  • Add JSON2 execution mode to endpoint.endpoint with JSON-2-specific configuration fields, validation, dispatch logic, and result shaping.
  • Add /json2/doc documentation controllers plus demo data, views, security access, and module metadata.
  • Add TransactionCase + HttpCase test suites covering core JSON2 behaviors (routing, validation, access, dotted fields, serialization, doc endpoint).

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
endpoint_json2/init.py Initializes addon subpackages.
endpoint_json2/manifest.py Declares addon metadata, dependencies, demo/data files.
endpoint_json2/controllers/init.py Registers controllers package.
endpoint_json2/controllers/main.py Implements /json2/doc endpoints for auto-generated JSON2 API docs.
endpoint_json2/demo/endpoint_json2_demo.xml Provides demo JSON2 endpoints and parameters.
endpoint_json2/models/init.py Registers JSON2 models.
endpoint_json2/models/endpoint_endpoint.py Adds JSON2 exec mode, config fields, validation, execution and response shaping.
endpoint_json2/models/endpoint_json2_param.py Defines JSON2 parameter model with type/default validation and extraction.
endpoint_json2/pyproject.toml Build metadata for the addon package.
endpoint_json2/README.rst Generated user-facing documentation for the addon.
endpoint_json2/readme/CONFIGURE.md Configuration guide (source for generated README).
endpoint_json2/readme/CONTRIBUTORS.md Contributors list.
endpoint_json2/readme/DESCRIPTION.md Short module description.
endpoint_json2/readme/USAGE.md Usage guide (calling endpoints and docs).
endpoint_json2/security/ir.model.access.csv Grants model access for JSON2 param model.
endpoint_json2/static/description/index.html Generated HTML description for Odoo Apps page.
endpoint_json2/tests/init.py Registers test modules.
endpoint_json2/tests/common.py Shared test setup helpers.
endpoint_json2/tests/test_endpoint_json2.py Transaction tests for model-level JSON2 behavior/validation.
endpoint_json2/tests/test_endpoint_json2_controller.py HttpCase tests for JSON2 execution and /json2/doc.
endpoint_json2/views/endpoint_views.xml Adds JSON2 configuration UI into endpoint form view.
Suppressed comments (2)

endpoint_json2/models/endpoint_endpoint.py:206

  • _json2_check_group_access denies access when json2_group_ids is empty, but the module docs describe empty Allowed Groups as meaning “any authenticated user”. This currently makes endpoints unusable unless at least one group is configured.
    def _json2_check_group_access(self, request):
        if not (self.json2_group_ids & request.env.user.all_group_ids):
            raise werkzeug.exceptions.Forbidden(
                "User does not belong to any allowed group"
            )

endpoint_json2/controllers/main.py:65

  • The 404 message uses “domain” terminology, but the path parameter is route_group (and the feature is documented as “route group”). Using consistent wording will make the error clearer for API consumers.
        endpoints = self._get_accessible_endpoints([("route_group", "=", route_group)])
        if not endpoints:
            raise NotFound(f"No endpoints found for domain {route_group!r}")
        return request.make_json_response(

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to +17
def _get_accessible_endpoints(self, extra_domain=None):
domain = [("exec_mode", "=", "json2")] + (extra_domain or [])
all_endpoints = request.env["endpoint.endpoint"].sudo().search(domain)
user = request.env.user
return all_endpoints.filtered(
lambda ep: ep.json2_group_ids & user.all_group_ids
)
Comment on lines +41 to +45
<field
name="json2_group_ids"
widget="many2many_tags"
required="exec_mode == 'json2'"
/>
Comment on lines +117 to +129
def _validate_exec__json2(self):
if not self.json2_model_id:
raise ValidationError(
self.env._("Exec mode is set to 'JSON-2 API': you must select a model.")
)
if not self.json2_method and not self.json2_code_snippet:
raise ValidationError(
self.env._(
"Exec mode is set to 'JSON-2 API': you must specify a method or "
"provide a code snippet."
)
)

@yostashiro
yostashiro force-pushed the add-endpoint_json2 branch 2 times, most recently from 0f0a554 to 019fcf9 Compare August 6, 2026 03:49
…umentation

Two configuration rules stated in CONFIGURE.md were not the rules the code
actually applied.

An endpoint whose Allowed Groups list is empty rejects every caller
(_json2_check_group_access) and never appears in /json2/doc, while the
documentation said an empty list allows any authenticated user. Failing closed
is the right default for something reachable over HTTP, and the form view
already marks the field required, so the behaviour stays and the documentation
is corrected -- backed by a constraint, so a data file or an import cannot
create an endpoint that nobody can call.

Method and Code Snippet are documented as mutually exclusive, but only "at
least one of them" was enforced; with both set the snippet silently won. The
form view hides one field while the other is set, so that state was reachable
only through a write, and _check_exec_mode is constrained on exec_mode alone,
so it never revalidated one. Both rules now live in constraints that depend on
the fields they check.

Assisted-by: Claude Opus 5
@yostashiro

Copy link
Copy Markdown
Member Author

@AungKoKoLin1997 Can you please reflect the recent changes to the OCA PR.

@yostashiro
yostashiro merged commit c7acf05 into 19.0 Aug 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants