Skip to content
Snippets Groups Projects
Verified Commit 96e5eb76 authored by Daniel Hornung's avatar Daniel Hornung
Browse files

DOC: More specs

parent ceff40d2
No related branches found
No related tags found
4 merge requests!100WIP: Filling XLSX: Seems to be working.,!94ENH: add framework for converting json schema into table templates,!93Filling XLSX: Everything except multiple choice.,!92ENH: xlsx template generator
Pipeline #47883 failed
This commit is part of merge request !94. Comments created here will be created in the context of that merge request.
# Konversion zwischen LinkAhead-Datenmodellen, JSON-Schema und XLSX (und zurück) #
Top level of json must be a dict. keys of the dict are RT names. Top level of json must be a dict. keys of the dict are RT names.
...@@ -6,12 +8,14 @@ Frage: is the first RT never an array? ...@@ -6,12 +8,14 @@ Frage: is the first RT never an array?
Do not use sheet name, but only content of hidden rows Do not use sheet name, but only content of hidden rows
## Datenmodelle in JSON-Schema und JSON-Daten ##
Das Datenmodell in LinkAhead legt fest, welche Arten von Records es in einer LinkAhead-Instanz gibt
und wie diese aussehen. Dieses Datenmodell kann auch in einem JSON Schema repräsentiert werden, dass
die Struktur von JSON Dateien festlegt, die zu dem Datenmodell gehörige Records enthält.
Das Datenmodell in LinkAhead legt fest, welche Arten von Records es in einer LinkAhead-Instanz
gibt und wie diese aussehen. Diese Datenmodell kann auch in einem JSON Schema repräsentiert werden,
dass die Struktur von JSON Dateien festlegt, die zu dem Datenmodell gehörige Records enthält.
Zum Beispiel kann das folgende JSON den Record einer Person beschreiben: Zum Beispiel kann das folgende JSON den Record einer Person beschreiben:
```JSON ```JSON
{ {
"Person": { "Person": {
...@@ -21,36 +25,48 @@ Zum Beispiel kann das folgende JSON den Record einer Person beschreiben: ...@@ -21,36 +25,48 @@ Zum Beispiel kann das folgende JSON den Record einer Person beschreiben:
} }
``` ```
Das JSON Schema schreibt eine konkrete Struktur vor und kann zugehörige JSON Dateien können genutzt werden Ein *JSON Schema* schreibt eine konkrete Struktur vor, und die zugehörige JSON Dateien können
um Daten zu bestimmten Record Strukturen zu repräsentieren. Beispielsweise könnte man ein JSON Schema erstellen, genutzt werden, um Daten zu bestimmten Record-Strukturen zu repräsentieren. Beispielsweise könnte
dass es erlaubt "Training" Records mit Informationen zu abgehaltenen Trainings speichern. Dies ist insbesondere wertvoll man ein JSON Schema erstellen, dass es erlaubt "Training" Records mit Informationen zu abgehaltenen
beim Datenim- und export. Man könnte basierend auf dem im Folgenden beschriebenen Webformulare basieren Trainings zu speichern. Dies ist insbesondere wertvoll beim Datenim- und export. Man
oder es nutzen um in LinkAhead gespeicherte Objekte als JSON zu exportieren. könnte Webformulare aus dem Json Schema generieren oder es nutzen, um in LinkAhead gespeicherte
Objekte als JSON zu exportieren.
Im Folgenden wird beschrieben, wie JSON Dateien mit solchen Records in XLSX Dateien umgewandelt
werden, bzw. wie aus XLSX-Dateien JSON Dateien mit Records erstellt werden. ## Von JSON zu XLSX: Datenrepräsentation ##
Der Attributname (oben "Person") legt den RecordType fest und der Wert diese Attributs kann Im Folgenden wird beschrieben, wie JSON Dateien, die LinkAhead-Records reprästentieren in XLSX
entweder ein Objekt oder eine Liste sein. Ist es ein Objekt (wie im obigen Beispiel), so wird ein Dateien umgewandelt werden, bzw. wie aus XLSX-Dateien JSON Dateien mit Records erstellt werden.
einzelner Record repräsentiert. Bei einer Liste mehrere Records, die den gleichen RecordType als
Parent haben. Der Attributname (oben "Person") legt den RecordType fest und der Wert diese Attributs kann entweder
Die Properties des Records (oben "family_name" und "given_name") werden zu Spalten im XLSX. ein Objekt oder eine Liste sein. Ist es ein Objekt (wie im obigen Beispiel), so wird ein einzelner
Die Properties haben wiederum einen Attributnamen und einen Wert. Der Wert kann Record repräsentiert. Bei einer Liste mehrere Records, die den gleichen RecordType als Parent
a. primitiv (Text, Zahl, Boolean, ...) haben.
b. ein Record
c. eine Liste von primitiven Typen Die *Properties* des Records (oben `family_name` und `given_name`) werden zu *Spalten* im XLSX. Die
Properties haben wiederum einen Attributnamen und einen Wert. Der Wert kann
a. primitiv (Text, Zahl, Boolean, ...)
b. ein Record
c. eine Liste von primitiven Typen
d. eine Liste von Records d. eine Liste von Records
sein. sein.
In den Fällen a. und c. wird in XLSX eine Zelle in der zur Property gehörigen Spalte erstellt. Im Fall b. In den Fällen *a.* und *c.* wird in XLSX eine Zelle in der zur Property gehörigen Spalte erstellt.
wird prinzipiell für die Properties des Records Spalten erstellt. Tatsächlich wird der referenzierte Record genauso behandelt wie Im Fall *b.* wird prinzipiell für die Properties des Records Spalten erstellt. Tatsächlich wird der
der ursprüngliche. D.h. die Fälle a.-d. werden wieder für die einzelnen Properties betrachtet. referenzierte Record genauso behandelt wie der ursprüngliche. D.h. die Fälle a.-d. werden wieder
Für den Fall d. ist die zweidimensionale Struktur eines XLSX Blatts nicht ausreichend. Daher werden für solche Fälle neue XLSX Blätter erstellt. für die einzelnen Properties betrachtet.
In diesen werden die referenzierten Records behandelt wie oben beschrieben. Es gibt jedoch zusätzliche Spalten die es erlauben zu erkennen von
welchem Record die Records referenziert werden. Für den Fall *d.* ist die zweidimensionale Struktur eines XLSX Blatts nicht ausreichend. Daher
werden für solche Fälle *neue* XLSX-Blätter/-Tabellen erstellt.
In diesen werden die referenzierten Records behandelt wie oben beschrieben. Es gibt jedoch
zusätzliche Spalten die es erlauben zu erkennen, von welchem "externen" Record diese Records
referenziert werden.
Wir betrachten diese vier Fälle nun im Detail: Wir betrachten diese vier Fälle nun im Detail:
a. Properties mit primitiven Datentypen
### a. Properties mit primitiven Datentypen ###
```JSON ```JSON
{ {
...@@ -63,38 +79,36 @@ a. Properties mit primitiven Datentypen ...@@ -63,38 +79,36 @@ a. Properties mit primitiven Datentypen
} }
} }
``` ```
Dies würde in einem XLSX Blatt mit dem folgenden Inhalt abgebildet: Dieser Eintrag wird in einem XLSX-Blatt mit dem folgenden Inhalt abgebildet:
| date | url | duration | participants | remote |
|------|-----|-------------------|-----|---|----|
| 2023-01-01 | www.indiscale.com | 1.0 | 1 | false |
b. Property, die einen Record referenziert | date | url | duration | participants | remote |
|------------|-------------------|----------|--------------|--------|
| 2023-01-01 | www.indiscale.com | 1.0 | 1 | false |
### b. Property, die einen Record referenziert ###
```JSON ```JSON
{ {
"Training": { "Training": {
"date": "2023-01-01", "date": "2023-01-01",
"supervisor": { "supervisor": {
"family_name": "Steve", "family_name": "Stevenson",
"given_name": "Stevie", "given_name": "Stevie",
} }
} }
} }
``` ```
Dies würde in einem XLSX Blatt mit dem folgenden Inhalt abgebildet: Dieser Eintrag wird in einem XLSX Blatt mit dem folgenden Inhalt abgebildet:
| date | supervisor.family_name | supervisor.given_name | | date | `supervisor.family_name` | `supervisor.given_name` |
|------|-----|-------------------| |------------|--------------------------|-------------------------|
| 2023-01-01 | Steve | Stevie | | 2023-01-01 | Stevenson | Stevie |
Beachten Sie, dass die Spaltennamen umbenannt werden dürfen. Die Zuordnung der Spalte zu Properties von Beachten Sie, dass die Spaltennamen umbenannt werden dürfen. Die Zuordnung der Spalte zu Properties
Records wird über den Inhalt von versteckten Zeilen gewährleistet. von Records wird über den Inhalt von versteckten Zeilen gewährleistet.
c. Properties, die Listen mit Werten von primitiven Datentypen enthalten
### c. Properties, die Listen mit Werten von primitiven Datentypen enthalten ###
```JSON ```JSON
{ {
...@@ -105,19 +119,16 @@ c. Properties, die Listen mit Werten von primitiven Datentypen enthalten ...@@ -105,19 +119,16 @@ c. Properties, die Listen mit Werten von primitiven Datentypen enthalten
} }
``` ```
Dies würde in einem XLSX Blatt mit dem folgenden Inhalt abgebildet: Dieser Eintrag würde in einem XLSX Blatt mit dem folgenden Inhalt abgebildet:
| url | subjects |
|------|-----|-------------------|-----|---|----|
| www.indiscale.com | Math;Physics |
Die Listenelemente werden separiert von ``;`` in die Zelle geschrieben. | url | subjects |
Wenn die Elemente den Separator ``;`` enthalten, dann wird dieser mit einem ``\`` escaped. |-------------------|--------------|
| www.indiscale.com | Math;Physics |
Die Listenelemente werden separiert von ``;`` in die Zelle geschrieben. Wenn die Elemente den
Separator ``;`` enthalten, dann wird dieser mit einem ``\`` escaped.
d. Properities, die Listen mit Referenzen enthalten ### d. Properties, die Listen mit Referenzen enthalten ###
```JSON ```JSON
{ {
...@@ -127,45 +138,92 @@ d. Properities, die Listen mit Referenzen enthalten ...@@ -127,45 +138,92 @@ d. Properities, die Listen mit Referenzen enthalten
{ {
"family_name": "Sky", "family_name": "Sky",
"given_name": "Max", "given_name": "Max",
},{ },
{
"family_name": "Sky", "family_name": "Sky",
"given_name": "Min", "given_name": "Min",
}], }
]
} }
} }
``` ```
Da die beiden Coaches nicht vernünftig in einer Zelle dargestellt werden können, bedarf es nun eines Da die beiden Coaches nicht vernünftig in einer Zelle dargestellt werden können, bedarf es nun eines
weiteren Tabellenblatts, das die Eigenschaften der Coaches enthält. weiteren Tabellenblatts, das die Eigenschaften der Coaches enthält.
Das Blatt zu den Trainings enthält in diesem Beispiel nur die "date" Spalte: Das Blatt zu den *Trainings* enthält in diesem Beispiel nur die "date" Spalte:
| date | | date |
|------| |------------|
| 2023-01-01 | | 2023-01-01 |
Zusätzlich gibt es ein weiteres Blatt in dem die Coaches gespeichert werden. Zusätzlich gibt es ein *weiteres* Blatt in dem die Coaches gespeichert werden. Hier ist nun
Hier ist nun entscheidend, dass definiert wird, wie von potentiell mehreren "Trainings" das richtige Element gewählt wird. entscheidend, dass definiert wird, wie von potentiell mehreren "Trainings" das richtige Element
In diesem Fall bedeutet dies, dass das "date" eindeutig sein muss gewählt wird. In diesem Fall bedeutet dies, dass das "date" eindeutig sein muss.
TODO: In welchem Scope gilt diese Eindeutigkeit? Können wir dies checken?
Das zweite Blatt sieht dann wie folgt aus
| date | coach.family_name | coach.given_name |
|------|-|-|
| 2023-01-01 | Sky | Max|
| 2023-01-01 | Sky | Min|
TODO: In welchem Scope gilt diese Eindeutigkeit? Können wir dies checken?
# Hidden automation logic Das zweite Blatt sieht dann wie folgt aus
The first column in each sheet will be hidden and it will contain an entry in each row that needs special
treatment. The following values are used:
``COL_TYPE``: typically the first row. It indicates the row that defines the type of columns (``FOREIGN`` or ``VALUE``).
``PATH``: indicates that the row is used to define the path within the JSON
``IGNROE``: row is ignored; It can be used for explanatory texts or layout
If we want to put the value of a given cell into the JSON, we traverse all path elements given in rows with the ``PATH`` value from row with lowest index to the one with the highest index. The final element of the path is the name of the Property of which the value | date | `coach.family_name` | `coach.given_name` |
needs to be set. The elements of the path are sufficient to identify the object within the JSON if the value of the corresponding key is |------------|---------------------|--------------------|
an object. If the value is an array, the appropriate object within the array needs to be selected. | 2023-01-01 | Sky | Max |
For this selection additional ``FOREIGN`` columns are used. The path given in those columns is the path to the level where the object needs to be chosen plus the name of the attribute that is used to select the correct object. | 2023-01-01 | Sky | Min |
## Data in XLSX: Hidden automation logic ##
### First column: Marker for row types ###
The first column in each sheet will be hidden and it will contain an entry in each row that needs
special treatment. The following values are used:
- ``IGNORE``: This row is ignored. It can be used for explanatory texts or layout.
- ``COL_TYPE``: Typically the first row that is not `IGNORE`. It indicates the row that defines the
type of columns (`FOREIGN`, `SCALAR`, `LIST`, `IGNORE`). This row may occur only once.
- ``PATH``: Indicates that the row is used to define the path within the JSON. These rows are
typically hidden for users.
An example table could look like this:
| `IGNORE` | | Welcome | to this | file! | |
| `IGNORE` | | Please | enter your | data here: | |
| `COL_TYPE` | `IGNORE` | `SCALAR` | `SCALAR` | `LIST` | `SCALAR` |
| `PATH` | | `Training` | `Training` | `Training` | `Training` |
| `PATH` | | `url` | `date` | `subjects` | `supervisor` |
| `PATH` | | | | | `email` |
| `IGNORE` | Please enter one training per line. | Training URL | Training date | Subjects | Supervisor's email |
|------------|-------------------------------------|----------------|---------------|--------------|--------------------|
| | | example.com/mp | 2024-02-27 | Math;Physics | steve@example.com |
| | | example.com/m | 2024-02-27 | Math | stella@example.com |
### Parsing XLSX data ###
To extract the value of a given cell, we traverse all path elements (in ``PATH`` rows) from top to
bottom. The final element of the path is the name of the Property to which the value belongs. In
the example above, `steve@example.com` is the value of the `email` Property in the path
`["Training", "supervisor", "email"]`.
The path elements are sufficient to identify the object within a JSON, at least if the corresponding
JSON element is a single object. If the JSON element is an array, the appropriate object within the
array needs to be selected.
For this selection additional ``FOREIGN`` columns are used. The paths in these columns must all have
the same *base* and one additional *unique key* component. For example, two `FOREIGN` columns could
be `["Training", "date"]` and `["Training", "url"]`, where `["Training"]` is the *base path* and
`"date"` and `"url"` are the *unique keys*.
The base path defines the table (or recordtype) to which the entries belong, and the values of the
unique keys define the actual rows to which data belongs.
For example, this table defines three coaches for the two trainings from the last table:
| `COL_TYPE` | `FOREIGN` | `FOREIGN` | `SCALAR` |
| `PATH` | `Training` | `Training` | `Training` |
| `PATH` | `date` | `url` | `coach` |
| `PATH` | | | `given_name` |
| `IGNORE` | Date of training | URL of training | The coach's given name |
| `IGNORE` | from sheet 'Training' | from sheet 'Training' | |
|------------|-----------------------|-----------------------|------------------------|
| | 2024-02-27 | example.com/mp | Ada |
| | 2024-02-27 | example.com/mp | Berta |
| | 2024-02-27 | example.com/m | Chris |
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment