Field types

JSON

Field type json. A list of entries, each with a label and the same subfields. Data entry from the cataloguer’s side is described under JSON .

JSON field Maßsatz (set of dimensions) in Moliri as a table with the columns Bereich (part), Höhe (height), Breite (width), Tiefe (depth) and Bemerkung (remark), one row each for Objekt (object) and Sockel (base)

The model

A JSON field has subfields (fields, the columns) and optionally labels (labels, the entries). view decides only whether it is displayed as tabs or as a table; switching it moves no data.

JSON
{
  "view": "tabs",
  "labels": ["Objekt", "Rahmen"],
  "creatable": true,
  "max": 1,
  "fields": [
    { "key": "hoehe",  "label": "Höhe",   "type": "number" },
    { "key": "breite", "label": "Breite", "type": "number" },
    { "key": "tiefe",  "label": "Tiefe",  "type": "number" }
  ]
}

Parameters

KeyValuesIf omittedEffect
viewtabs, tablenoneDisplay. Without this key the field shows “no fields configured”
labelsList of stringsemptyThe available entries. If the list is missing and creatable is off, there is no label level
creatabletrue, falsefalseCreate, rename and remove labels of your own
show_alltrue, falsetrueShows all configured labels, including empty ones. false: only filled ones, the rest through the plus
maxNumber or null1Entries per label. null means any number
fieldsListemptyThe subfields, the same for all labels
outputObject or listemptyOutput formatter, see below

The label is also the key in the stored value. If you rename a label in the configuration, the old data stays under the old label. It remains visible and is marked as not configured; moving it is manual work.

Subfields

KeyIf omittedMeaning
keyKey in the stored value
labelsame as keyLabel or column heading
typetexttext, multiline, number, date, select, switch, reference. An unknown type becomes text
valuesemptyselect only: values offered
freefalseselect only: free text with suggestions instead of a fixed list
librarynonereference only: normdata, address or object, see References
target_project_idthe field’s projectreference to object only: the project to choose from
label_fieldnonereference to object only: field name of the title in the target project
object_typesallreference to object only: allowed object types, as a list or comma-separated
widthautomaticWidth of the table column, for example 6rem
requiredfalseEmpty produces a hint. Never blocks
placeholderemptyPlaceholder text

Short form: "fields": ["hoehe", "breite"] gives text fields whose key is the same as their label.

A date subfield shows the date picker as long as the value is empty or in ISO format; an existing 14.02.2026 stays a text field. A select value outside the list is added rather than discarded.

References

A column of type reference points to an entry in a library. Only its identifier is stored, never the label; Moliri looks the label up when it displays the value.

libraryTargetStoredSelection
normdataan authority recordthe authority record ID, an integeras in the authority field
addressa person in the address bookthe person ID, a string of up to 36 charactersas in the address field
objectan objectthe object ID, an integeras in the object field , without the object being edited

Object references have three further column options, named as in the object field:

KeyIf omittedEffect
target_project_idthe field’s projectThe project to choose from
label_fieldnoneIts value appears in the cell before project and inventory number and is searched in the selection
object_typesallOnly objects of these object types can be chosen, for example ["literatur"]. In lower case

An example: loans with lender and loan agreement for each venue.

JSON
{
  "view": "table",
  "max": null,
  "fields": [
    { "key": "station",   "label": "Station",    "type": "text" },
    { "key": "leihgeber", "label": "Leihgeber",  "type": "reference", "library": "address" },
    { "key": "ort",       "label": "Ort",        "type": "reference", "library": "normdata" },
    { "key": "vertrag",   "label": "Leihvertrag", "type": "reference", "library": "object",
      "target_project_id": 7, "label_field": "Titel", "object_types": ["vertrag"] }
  ]
}

What is stored is then something like [{"station": "Berlin", "leihgeber": "a3f9…", "ort": "1204", "vertrag": "8812"}]. If library is missing or unknown, the cell shows the stored identifier as text and offers no selection. If an identifier does not fit the library, such as letters with normdata, the cell carries the note ID does not match the library. Without read permission on the target, or if it has been deleted, the identifier appears instead of the label.

A reference in a JSON field is not a link : it has no counterpart at the target, and the target knows nothing about it. It suits details that belong to an entry, such as the person who handled a movement. Anything that is a statement of its own about the object becomes a link or an object field .

In the export the reference stays the identifier. In the Excel export and in the export to a standard, an output formatter also finds the label of an object reference in zeilen, under ⟨key⟩~label, in the example vertrag~label. Authority data and address references stay identifiers there.

What is stored

The form collapses as far as the configuration allows:

ConfigurationStoredAccess
Labels, max: 1, one subfield{"de": "Bildnis einer Dame"}Titel.de
Labels, max: 1, several{"Objekt": {"hoehe": "118,5", "breite": "64"}}Maße.Objekt.breite
Labels, max greater than 1 or null{"Objekt": [{…}, {…}]}Maße.Objekt[0].breite
no labels, one subfield["INV 2019/0412", "INV 2019/0413"]Inv[0]
no labels, several[{"hoehe": "118,5"}, …]Inv[0].hoehe

If you change max or the number of subfields, from then on a different form is written than the existing data has. Every form can be read. Entries are written as strings ("1" instead of 1), because 118,5 is not a JSON number anyway. A field that has never been filled is an empty string and counts as empty everywhere. Subfield keys that the configuration does not know are kept.

Output formatter

An output block makes the variant “Formatted” available in the export, and in the gallery, table and kanban as well. It has two bodies:

JSON
{
  "output": {
    "entry": { "js": "return sub['hoehe'] + ' × ' + sub['breite'] + ' cm';" },
    "total": { "js": "return verbinde(zeilen, '{__label}: {formatiert}', '; ');" },
    "label": "Maße kurz"
  }
}

entry formats one entry (118,5 × 64 cm), total the whole field (Objekt: 118,5 × 64 cm; Rahmen: 130 × 75 cm). If total is missing, the entry results are joined with ;. label names the formatting in the selection and the column heading.

Several formattings are written as a list, each with an identifier name. The variant standard is the one addressed by the plain field name; the others are called Maße#kurz in templates.

Name in the bodyin the entry bodyin the total body
wertthe label of the entrythe raw value of the field
subthe values of the entrythe subfields of the field
zeilenthis entry as a listall entries, each with formatiert and __label in addition
cfg('key')the field’s own configurationthe same
meta('key')annotations of the data field: source, comment, colour, uncertain, modifierthe same
leer, spalte, verbinde, tab, maskehelpersthe same

A formatter sees only its own field. If you calculate across several fields, use a virtual field ; it can call up the finished formatter of a JSON field with fmt('Maße').

The field type itself comes with the formatting Entries on one line. How the field type’s defaults and formattings of your own work together, and which language features are allowed in the body, is described under Formatting .

Standards and import

A JSON field can serve a repeatable concept of a metadata standard, one instance per entry. The pseudo column __label then carries the language of a title or what a dimension refers to. See Metadata standards .

In the Excel import a JSON field accepts a complete document, a value under a chosen label, columns mapped to individual keys of an entry, or plain text that the cleanup step Convert text to JSON converts. Everything else is parked. See JSON targets . Two parameters control the import:

Parameter (in the form)KeyIf omittedEffect
Label on importimport_labelnoneLabel that the Excel import preselects on every column mapped to this field, for example de. Resolve references suggests it too when a text is assigned to a key. Fill in then only checks whether something is already stored under this label
Append on importimport.appendtrueStarting value of the switch Append on key columns: true appends a new entry per row, false replaces the existing entries (under the label). Only with several entries per label

Switching from text to JSON

Text and JSON store their values the same way, so a text field can be switched to JSON. The values stay plain text, and the field shows them as raw content. The cleanup step Convert text to JSON splits such text at a separator and fills the keys in order; the keys are prefilled with the columns of the field. Clean existing values in the field details converts the whole collection, first as a trial run and then for real. With the step in the chain, the Excel import also accepts plain text instead of parking it. See Cleanup .

Examples

Title in three languages:

JSON
{
  "view": "tabs",
  "labels": ["de", "en", "es"],
  "creatable": true,
  "max": 1,
  "fields": [{ "key": "titel", "label": "Titel", "type": "text" }],
  "output": {
    "total": { "js": "return verbinde(zeilen, '{__label}: {titel}', '; ');" },
    "label": "Alle Sprachen"
  }
}

Dimensions with what they refer to, repeatable:

JSON
{
  "view": "table",
  "labels": ["Objekt", "Rahmen", "Passepartout"],
  "creatable": true,
  "show_all": false,
  "max": null,
  "fields": [
    { "key": "art", "label": "Art", "type": "select", "free": true,
      "values": ["Höhe", "Breite", "Tiefe", "Gewicht"], "width": "7rem" },
    { "key": "wert", "label": "Wert", "type": "number", "required": true, "width": "5rem" },
    { "key": "einheit", "label": "Einheit", "type": "select", "free": true,
      "values": ["cm", "mm", "m", "g", "kg"], "width": "4.5rem" }
  ],
  "output": {
    "entry": { "js": "return sub['art'] + ' ' + sub['wert'] + ' ' + sub['einheit'];" },
    "total": { "js": "return verbinde(zeilen, '{__label}: {formatiert}', '; ');" }
  }
}

Inventory numbers without a label:

JSON
{ "view": "table", "max": null, "fields": [{ "key": "nr", "label": "Nummer" }] }

When another field type fits

As soon as one of the values is searched for, sorted or grouped, it belongs in a field of its own. For a construct that is not a list of uniform entries there is JSON schema . For a single value the structure is not worth it.