View · Index

Handling JSON Requests with page contracts

The newest versions of OpenACS (head) and NaviServer (5.1) can now process JSON request bodies in the same convenient way as classic HTML form submissions. When a request is sent with a JSON media type (including structured suffix types such as application/*+json), NaviServer parses the JSON payload automatically and flattens it into the connection form set. This enables using ad_page_contract for validation and makes JSON requests first-class citizens in existing OpenACS applications.

On validation failures, OpenACS can return a standards-based error response using RFC 9457 (application/problem+json) and can include JSON Pointer references (RFC 6901) to pinpoint the offending fields.

Overview

  • Automatic JSON parsing: JSON request bodies are parsed and exposed through ns_getform/ns_conn form as an ns_set.
  • Typed values: The flattened representation includes .type sidecar keys (e.g., user/id.type, user/flags/admin.type) to preserve JSON typing.
  • JSON Pointer addressing (RFC 6901): When reporting errors (and when navigating typed JSON structures via the ns_json triples ensemble), JSON Pointer provides an interoperable path syntax such as /user/flags/admin.
  • Problem Details errors (RFC 9457): Contract violations for JSON requests can return 422 Unprocessable Content with application/problem+json.

Sending JSON Requests

Clients should send JSON with an appropriate Content-Type header:

Content-Type: application/json

Structured syntax suffixes are supported as well:

Content-Type: application/vnd.api+json

Using ad_page_contract with JSON

In OpenACS, you can validate JSON-derived values using ad_page_contract. Because the JSON body is flattened into an ns_set, contract parameter names can refer to nested JSON fields using a slash-separated naming convention.

Example OpenACS page

ad_page_contract {
    test_page
} {
    {user/id:naturalnum 0}
    {user/flags/admin:boolean}
}

ns_return 200 application/json [subst {{"result":"OK", "user_id":${user/id}}}]

The contract declares two inputs:

  • user/id must be a natural number (integer >= 0) and defaults to 0
  • user/flags/admin must be a boolean

Example Request Payload

Submitted JSON data:

{"user": {
    "id":-7,
    "name":"Alice",
    "flags":{
        "admin":"xxx",
        "active":true
    }}
}

Validation Failure Response (RFC 9457 + RFC 6901)

When the request body was parsed as JSON and validation fails, OpenACS can return a Problem Details document (application/problem+json) with status 422. Each error includes a JSON Pointer fragment (#/...) referencing the offending field in the request document.

{
  "type": "https://openacs.org/validation-error",
  "title": "We had a problem with your input:",
  "status": 422,
  "errors": [
    {
      "detail": "user/id is not a natural number, that is an integer greater than or equal to 0.",
      "pointer": "#/user/id"
    },
    {
      "detail": "user/flags/admin does not appear to be a Boolean value.",
      "pointer": "#/user/flags/admin"
    }
  ]
}

Notes

  • The type field is a stable identifier (a URI) for the class of problem. It may be used by clients for automatic handling and may also point to documentation.
  • The title and detail fields are intended for humans and may be localized. Clients should not rely on localized text for program logic.
  • The pointer values use JSON Pointer fragment identifiers (#/...), consistent with the Problem Details ecosystem. The corresponding JSON Pointer path without fragment prefix would be /user/id, /user/flags/admin, etc.

Optional: Typed JSON Navigation with ns_json triples

For applications that need to navigate and update JSON while preserving JSON types (numbers, booleans, null, arrays, objects), NaviServer provides the ns_json triples ensemble. It supports addressing via Tcl list paths or JSON Pointer (RFC 6901) and can generate JSON output directly from triples without lossy conversions. Alternatively of using the ns_set provided by ns_getform, one can get the body of the request and process the included JSON, extract parts of it, etc.

Typical flow:

set t [ns_json parse -output triples $json]
ns_json triples getvalue -pointer /user/flags $t
set t2 [ns_json triples setvalue -pointer /user/flags/admin -type boolean $t true]
ns_json triples getvalue -pretty -pointer /user/flags $t2

See Also

previous February 2026
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 (1) 23 24 25 26 27 28

Popular tags

17 , 5.10 , 5.10.0 , 5.10.1 , 5.9.0 , 5.9.1 , ad_form , ADP , ajax , aolserver , asynchronous , Azure , bgdelivery , bootstrap , bugtracker , CentOS , COMET , compatibility , conference , CSP , CSRF , cvs , debian , docker , docker-compose , emacs , engineering-standards , exec , fedora , FreeBSD
No registered users in community xowiki
in last 30 minutes
Contributors

OpenACS.org