openEHR Reference Model in JSON format

A while ago, I was tasked with creating a (nearly) complete list of all attributes that can be stored in a composition as defined by the openEHR reference model.

The goal was to compile an example of all paths that can be populated with information when creating a composition for the Clinical Data Repository (CDR). Understanding these paths also facilitates formulating AQL queries.

For instance, an end time for the context can be stored at: context/end_time/value
Similarly, the ID of an external reference of the composer can be stored at: composer/external_ref/id/value

Initially, I manually created this list by navigating through various web pages of the reference model and constructing the paths myself. This process was quite tedious, so we developed a script to scrape the reference model pages, extracting all tables containing class information.

The outcome is a JSON file containing all classes and attributes, which can be easily processed by machines.

I am sharing the JSON file here because it could be beneficial for anyone encountering a similar challenge.

Furthermore, this initiative might inspire future revisions of the reference model to be published in a similar machine-readable format.

20250116_openEHR_RM.json (207.2 KB)

I am also sharing an excel file as an example of the path list that can be created automatically.

20250116_RM_path_output.xlsx (165.5 KB)

1 Like

Great initiative @Martin_Koch to better understand the information that gets stored in a CDR.

You can compare the JSON created via scraping to the “official” computable representation of the RM found in BMM files: specifications-ITS-BMM/components/RM/Release-1.1.0 at master · openEHR/specifications-ITS-BMM · GitHub

Your JSON includes descriptions that are not present in the BMM files and are only part of the HTML ( :clap:). To avoid scraping the openEHR site, you could work directly on AsciiDoc files: specifications-RM/docs at master · openEHR/specifications-RM · GitHub

There are also an alternative UML diagrams (with descriptions): NeoEHR

Thanks Martin,

This is incredibly useful, many thanks for this contribution. The good news is that the RM changes so slowly (for mostly good reasons) that keeping it current may not be quite as hard, though @borut.jures suggestions are helpful.

We need to think about how to make this a bit easier to maintain, and of course, translate.

One minor suggestion, which is to change ‘occurence’ to ‘existence’, which is as I understand it , what applies to RM attributes, whereas ‘occurrence’ applies to any overlying archetype constraint.

From the top of my memory, existence indicates an attribute having value, and occurence indicates cardinality of the values. Happy to be corrected.

Thank you so much for the comments.

@borut.jures When looking into the BMM, I have found a JSON version here: specifications-ITS-BMM/adl_test/Release-1.0.0/BMM/json at master · openEHR/specifications-ITS-BMM · GitHub
Maybe I have “re-invented the wheel” here :smiley: .

@ian.mcnicoll I am certainly going to have a look into the difference of occurrence vs existence.

Me too - I may not be quite right about ‘existence’ in this context @borut.jures - do you have any thoughts on this.

From what I can see BMM expresses existence as a isMandatory boolean - as per @Seref’s interpretation,

1 Like

A constraint on occurrences is used only with cADL object nodes (not attribute nodes), to indicate how many times in runtime data an instance of a given class conforming to a particular constraint can occur. It only has significance for objects which are children of a container attribute, since by definition, the occurrences of an object which is the value of a single valued attribute can only be 0..1 or 1..1 , and this is already defined by the attribute existence

Archetype Definition Language 1.4 (ADL1.4)

The above is what I was remembering. I’m too busy to check but why would we have these in any representation of the rm? These are constraints to be applied on rm, not properties of RM classes. Have I completely forgotten the basics? :slight_smile:

1 Like

These two are both defined in AM BMM (for constraints as already mentioned):

  • C_ATTRIBUTE.existence
  • C_OBJECT.occurrences

Example of an AM JSON:

  • existence defines that the attribute category is required in a RM type/class
  • occurrences defines that the categoryattribute is always of type DV_CODED_TEXT as a single element and not a list of DV_CODED_TEXT items
    "attributes": [
      {
        "_type": "C_ATTRIBUTE",
        "rm_attribute_name": "category",
        "existence": {
          "_type": "Multiplicity_interval",
          "lower": 1,
          "upper": 1,
          "lower_unbounded": false,
          "upper_unbounded": false,
          "lower_included": true,
          "upper_included": true
        },
        "children": [
          {
            "_type": "C_COMPLEX_OBJECT",
            "rm_type_name": "DV_CODED_TEXT",
            "occurrences": {
              "_type": "Multiplicity_interval",
              "lower": 1,
              "upper": 1,
              "lower_unbounded": false,
              "upper_unbounded": false,
              "lower_included": true,
              "upper_included": true
            },

occurrence in JSON is parsed from the Attributes column of the “blue” tables that describe an RM class. This column shows the existence which can be one of two values: 0…1, 1…1 (basically true/false defining if the attribute is mandatory).

occurrence in @Martin_Koch JSON is not the same as C_OBJECT.occurrences. It should be existence or is_mandatory (as proposed by @ian.mcnicoll).


@Martin_Koch Note that cardinality = <|>=0|> is missing in JSON (for example ADDRESSED_MESSAGE.addressees in JSON):

        "ADDRESSED_MESSAGE": {
            "attributes": {
                "addressees": {
                    "occurrence": "1..1",
                    "type": [
                        "List",
                        "String"
                    ]
                },

…while in BMM:

 	["ADDRESSED_MESSAGE"] = <
		properties = <
			["addressees"] = (P_BMM_CONTAINER_PROPERTY) <
				type_def = <
					container_type = <"List">
					type = <"String">
				>
				cardinality = <|>=0|>
			>

We have 3 somewhat confusing properties: existence, occurrences and cardinality :wink:

1 Like

The JSON file you found is essentially BMM as JSON (from what I understand) which is fine but a bit abstract, whereas your approach adds some helpful implications for human consumers as well as the node descriptions, so you are absolutely not re-inventing the wheel.

I can use what you have delivered right out of the box to support a pice of work I am doing, and will save a ton of work.

1 Like

It is confusing so here is my understanding, and thinking aloud as I 've dived into BMM and P_BMM

BMM expresses 4 ideas

is_mandatory: boolean - is the attribute mandatory or not (may be deprecated in favour of is_nullable)

‘existence()’ : A function which expresses ‘Is_mandatory’ in ‘0…1’ or ‘1…1’ format.

Note that there is no idea as existence ‘0…*’ - where a container of some sort (array, list etc) is needed, then this is expressed as

aList: string

So this where cardinality comes in and applies only to containers.

'cardinality`: The number of items that can be carried in a container.

I suspect that at RM level this is largely used to set a minimum of ‘1’ for containers, where the parent attribute is optional, which essentially prevents an empty container object.

e,g, from the EVENT_CONTEXT class

	["participations"] = (P_BMM_CONTAINER_PROPERTY) <
				name = <"participations">
				type_def = <
					container_type = <"List">
					type = <"PARTICIPATION">
				>
				cardinality = <|>=1|>
			>

There is no is_mandatory attribute on participations but if you add a participations object, the cardinality is ‘>=1’ i.e it cannot be empty. This is a universal rule in openEHR but I was never sure how it was expressed technically (it does not appear in the UML AFAICT.

When we get int o applying archetype constraints on top of the RM (AOM) we have 2 concepts that essentially mirror the BMM concepts

C_EXISTENCE: which would allow us to assert that an optional attribute in the RM is mandatory in the archetype/template.

C_CARDINALITY: which allows us to adjust the allowed number o items in a container. Some archetype editors used to allow this to be set but the general consensus was that cardinality, though potentiuallity quite elegant , was actually very confusing for modellers, particularly when set alongside ’ occurences’ which is new idea in the AOM, and much more useful.

‘occurrences’: within a container object, how many times can a specific child object appear. This is what we apply when we say that an ELEMENT or CLUSTER is ‘0…*’ etc

whereas ‘cardinality’ is the number of children (orf any type( that can appear in the container.

You can see how this could allow some very creative use of a mix of cardinality/ occurrences to express e.g optionality but it just got too hard for most of us to apply safely and explain to others.
So although existence and cardinality statements appear in raw ADL, they are not supported (correctly IMO) in most tooling UI.

So my take , finally is that @Martin_Koch would be better to change occurrences' to 'existence or 'is_mandatory`which is actually the original constraint.

1 Like

To follow-up, the other critical thing that has been added in your JSON, is of course the description, which does not appear in BMM in any way. So the question is if/how we can make that process a bit less onerous in the future so that e.g the Ascidocs which are the source of truth for the text, can be easily parsed to connect the descriptions to e.g some sort of format derived from BMM.

The P_BMM flavour is actually very nicely expressed - export that as JSON, add a description pulled from Asciidocs , clearly tagged with the corresponding P_BMM statement, and I think we have something very interesting.

https://specifications.openehr.org/releases/ITS-BMM/development/components/RM/latest/openehr_rm_ehr.bmm

1 Like

AM and RM as JSON (from BMM files with descriptions, variants and methods from Asciidocs):

2 Likes

I am attaching an updated version of the JSON here.

“occurrence” has been changed to “existence”, as was suggested.

20250120_openEHR_RM.json (206.9 KB)

2 Likes