Parsware
All articles

Parsware Platform

Schemas: every artifact is a file

Every table, view, form, query, report and process you build in Parsware is a plain JSON document underneath, and every kind has a published schema. So a document can be written in an editor, by a script or by an AI assistant, checked before it's sent, and the platform checks it again the same way the designer's own are. We wrote a saved query by hand.

The Query designer running a hand-written saved query, Visitors by purpose: three groups, Meeting, Delivery and Interview, next to the title "Schemas: every artifact is a file"

Everything you build in Parsware, a table, a view, a form, a query, a report, a process, an app, is a plain JSON document underneath. The designers draw it and write it for you, but it's never a picture only the designer understands. Each kind of document has a published schema that says exactly what a valid one looks like.

That has three consequences worth knowing:

  • A document can be written outside the designer: in an editor, by a script, or by an AI assistant that's been handed the schema.
  • It can be checked before it's sent, with any JSON Schema tool.
  • The platform checks it the same way whoever wrote it. There's no shortcut for the designer and no back door for a file: a save and a solution import both go through the same check.

See the file

Open a saved query, Visitors by company in the Visitors solution, and switch to its JSON tab. The designer's drawing is this document:

The Query designer for Visitors by company on its JSON tab: the query document with entity nw_visitor, aggregate grouping by nw_company and counting visitors, ordered by visitors descending

Where the schemas are

The developer help publishes every schema, 31 of them, each at /schemas/<name>.schema.json: a table is model-driven-entity, a view model-driven-view, a query parsware-query, a saved query saved-query, a report model-driven-report, a process bpms-process, a whole solution solution-package. The Artifact Schemas page lists them all.

Write one by hand

Reception wants a second question next to the first: how many visitors came for each purpose. Here it is, written in an editor:

{
  "logicalName": "nw_visitorsbypurpose",
  "displayName": "Visitors by purpose",
  "publisherPrefix": "nw",
  "description": "How many visitors came for each purpose, most first.",
  "query": {
    "entity": "nw_visitor",
    "aggregate": {
      "groupBy": [{ "field": "new_purpose" }],
      "measures": [{ "alias": "visitors", "function": "Count" }]
    },
    "order": [{ "field": "visitors", "descending": true }]
  }
}

The outside is a saved query; the query inside is a query document, with its own schema. Check each against its own, as the platform does:

$ npx ajv-cli validate --spec=draft2020 -s saved-query.schema.json -d visitors-by-purpose.json
visitors-by-purpose.json valid
$ npx ajv-cli validate --spec=draft2020 -s parsware-query.schema.json -d query.json
query.json valid

Send it

In the Visitors solution, open Saved Queries, then New. The name, logical name and description boxes hold the outside of the file; paste the query part into the JSON tab and Save. Preview runs it:

The new saved query Visitors by purpose, nw_visitorsbypurpose, on its Results tab: three groups, Meeting 4, Delivery 2, Interview 2

It's now a saved query like the one the designer drew. Its Simple and Advanced tabs show it as a drawing, and an app or a report can run it by name.

When it's wrong

Write "Total" where the schema says a measure's function is one of Count, Sum, Avg, Min or Max, and Save refuses it, saying where:

The Query designer refusing the hand-written query: The query document is not valid: /aggregate/measures/0/function enum: Value should match one of the values specified by the enum

The path, /aggregate/measures/0/function, is the same one ajv would have named. A misspelt property is refused the same way: "ordr" comes back as /ordr is not allowed here: the schema does not name it. A field that's spelled right but doesn't exist on the table gets past the schema and is caught next, when the query is checked against Visitors itself.

Solutions are files too

A solution package is the same idea one level up: a solution-package document carrying every component's document. Importing one checks the package against its schema and then each component against its own, so a solution generated by a script is checked exactly like one exported from Development.

What we fixed

  • Saving didn't check what you wrote. The designer's Save read the query into the platform's own shape first and checked the schema after. By then a property the schema doesn't name had been dropped, so "ordr" saved without a word, and an unknown function failed with One or more validation errors occurred, which says nothing. Save now checks the text you sent, and so does importing a solution.
  • A refused property was described, not named. The platform's message for a property the schema doesn't have was All values fail against the false schema. It now says the property is not allowed here: the schema does not name it, everywhere a document is checked.
  • A total grouped by a choice showed numbers. Visitors by purpose previewed as 270150000, 270150001, while the same column read Meeting in a list. Grouped results now carry the option's label, in the designer, in charts and reports, and for an app.
  • The schemas page listed nothing. The developer help's Artifact Schemas page still said the section was "intentionally empty" while the site served 31 schemas, 18 of which weren't linked from anywhere. It now lists every one, says how to check a document against it, and that a document holding another, like a saved query's query, is checked against both. In all seven languages.

Good to know

  • A schema is a contract, not a suggestion. A property the schema doesn't name is refused, not ignored, so a typo in a property name is caught rather than silently lost.
  • Old shapes stay valid where they must. When a document's shape changes in a way old files can't meet, the old schema is kept beside the new one so a solution exported before the change still imports.
  • The published copies are the platform's own. A test fails the build when a published schema differs from the one its service validates with.

Try it

Pick a view you use, open its JSON, and find each part of it in the model-driven-view schema. Then write a saved query of your own in an editor, check it with ajv, and paste it in.

Next: Build a custom React app.