You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e7ace3f
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/features/api-contract.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -295,11 +295,11 @@ never consulted**: the selector is the query parameter, in every port.
295
295
| Request | Answer |
296
296
|---|---|
297
297
| no `format`| Exactly the list route above: same body, same headers, same caps. |
298
-
|`format=json`| The list route's JSON array, unchanged, plus `Content-Disposition`. `Content-Type: application/json`. |
298
+
|`format=json`| The list route's JSON body, unchanged, plus `Content-Disposition`: the array, or with `withCount=1` the `{ rows, total }` envelope. `Content-Type: application/json`. |
| any other value (`xlsx`, `pdf`, `CSV`, empty) |`400 { "error": "invalid_format", "expected": ["csv", "json", "xml"] }`. `expected` lists the formats this route wires, in that order. `xlsx` is reserved for a later generator (`report-export-xlsx`) and is refused today like any unknown value. Matching is case-sensitive. |
302
-
|`format` set and `withCount` truthy |`400 { "error": "export_with_count" }` (`message` is free prose). An export has no`{ rows, total }` envelope, JSON included. |
302
+
|`format=csv` or `format=xml`and `withCount` truthy |`400 { "error": "export_with_count" }` (`message` is free prose). Only JSON carries the`{ rows, total }` envelope. |
303
303
| more rows than `maxRows`|`400 { "error": "export_too_large", "maxRows": N }` before a byte of the body is written. |
304
304
305
305
-**Header comparison.** Header names are case-insensitive. A runner compares `Content-Type` with the whitespace around `;` normalized (`text/csv;charset=utf-8` equals `text/csv; charset=utf-8`), because some servers re-spell it; every other header is compared exactly.
declares `xmlns:xsi`. That is what `XmlSerializer` writes for a nullable value type and what
372
372
`DataContractSerializer` writes for any null, and it keeps a null apart from an empty string. `Empty`
373
373
writes a bare empty element and declares nothing.
374
-
-**JSON** is the list route's array through the host's configured JSON options (so a `wire` setting and
374
+
-**JSON** is the list route's body (the array, or `{ rows, total }` with `withCount`) through the host's configured JSON options (so a `wire` setting and
375
375
a `JsonStringEnumConverter` apply as on the list route), served as `application/json`.
376
376
- A character XML 1.0 cannot carry is written as U+FFFD rather than failing the export.
Copy file name to clipboardExpand all lines: docs/ports/java.md
+15-11Lines changed: 15 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -447,27 +447,31 @@ generates nothing. The contract is in
447
447
448
448
`GET <apiPrefix>/<segment>?format=csv|json|xml` downloads a served report's rows (the contract is
449
449
[api-contract](../features/api-contract.md#report-export), the how-to
450
-
[reporting](../features/reporting.md#exporting-a-report)). Two entries turn it on, and both are
451
-
needed: wire the `report-export`generator, and give the `routes` generator the arg
452
-
`<reportExport>true</reportExport>`. The routes arg is what mounts the `format` branch in each report
453
-
`<R>Controller`(the generator list is not visible to a sibling generator, so the wiring is a
454
-
visible arg, not a guess); the branch reads its cap from `<R>Export.MAX_ROWS`, so the cap is set
455
-
once, as `maxRows` on `report-export`. A project with the arg unset gets controllers byte-identical to
456
-
today, and `?format=` is ignored like any unknown parameter.
450
+
[reporting](../features/reporting.md#exporting-a-report)). Wire the `report-export` generator to turn
451
+
it on. The Maven plugin hands the whole configured generator list to the `routes` generator
452
+
(`com.metaobjects.generator.RunAware`), which mounts the `format` branch in each report
453
+
`<R>Controller`when that list holds a `report-export` generator (`EmitsReportExport`, so an
454
+
ejected copy counts too). The branch reads its cap from `<R>Export.MAX_ROWS`, so the cap is set
455
+
once, as `maxRows` on `report-export`. A project that does not wire it gets controllers
456
+
byte-identical to today, and `?format=` is ignored like any unknown parameter.
457
457
458
458
With `?format` set the export cap (`maxRows`, default 100,000) governs and `report_too_large` never
459
459
answers; without it `reportMaxRows` (default 10,000) is untouched. The handler reads `maxRows + 1`
460
460
rows and answers `export_too_large` before writing a byte. The request side (format parsing, the
461
461
three 400 envelopes, the `Content-Disposition` and `Content-Type` values) is
462
462
`com.metaobjects.generator.spring.runtime.ReportExport`, a JDK-only class. (The Kotlin port generates its own copy of these helpers into its writer module.) With the branch mounted, the list route answers an explicit `application/json`, so a
463
463
request's `Accept` header is never consulted (a client sending `Accept: text/csv` without `format`
464
-
still gets JSON, not a 406). `withCount` is read as text on such a route (`1` or `true`).
464
+
still gets JSON, not a 406). `withCount` is read as text on such a route: `1` or `true` with `csv` or
465
+
`xml` is `export_with_count`, and `format=json&withCount=1` is the list route's `{ rows, total }`
466
+
envelope.
465
467
466
468
`xmlNulls` defaults to `empty`: a null field is an empty element, which is what Jackson's XML mapper
467
469
writes for a null, the Java standard (ADR-0019 Amendment 2). `nil` writes `xsi:nil="true"` and declares
468
-
`xmlns:xsi` on the root. A decimal cell is its canonical plain string (no exponent, no trailing zeros)
469
-
under either `wire` setting, and an array or map dimension is its compact JSON text. The JSON export is
470
-
the list route's array through the application's `ObjectMapper`, so a `wire` setting applies to it as
470
+
`xmlns:xsi` on the root. A decimal cell is written as the `wire` setting writes the list route: under
471
+
`decimals: string` its canonical plain string (`12.5`), under the default `native` what Jackson writes
472
+
for a `BigDecimal` (`12.50`). A time or a zone-less timestamp keeps its seconds (`10:00:00`), as
473
+
Jackson's JSR-310 serializers write it, and an array or map dimension is its compact JSON text. The JSON export is
474
+
the list route's body through the application's `ObjectMapper`, so a `wire` setting applies to it as
471
475
it does to the list. CSV and XML are written as `byte[]`, which every Spring MVC setup has a converter
0 commit comments