LHNCBC / formbuilder-lhcforms

Build LHC-Forms and FHIR Questionnaires
Other
28 stars 22 forks source link

Able to create and export complex Questionnaire that does not pass FHIR v4 schema validation #62

Open gularj2 opened 1 year ago

gularj2 commented 1 year ago

When testing application output using the Form Builder, I was able to create and export a complex Questionnaire that then does not pass FHIR 4.0 schema validation.

The form that is giving errors is included at the end of the post. Code Snippet:

def test_complex():
    import json
    import jsonschema

    with open("complex.json", "r") as f:
        complex = json.load(f)

    with open("fhir_schema_4.json", "r") as f:
        schema = json.load(f)

    jsonschema.validate(instance=complex, schema=schema)

The error is broken into the three parts:

troublesome form:

{
  "resourceType": "Questionnaire",
  "title": "Complex Survey",
  "status": "draft",
  "item": [
    {
      "code": [
        {
          "system": "http://loinc.org",
          "code": "30525-0",
          "display": "Age"
        }
      ],
      "text": "How old are you?",
      "type": "integer",
      "extension": [
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "a"
            },
            "display": {
              "unit": "a"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "a",
            "display": "year"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "a",
            "display": "year"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "code": "year",
            "display": "year"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "a",
            "display": "year"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "a",
            "display": "year"
          }
        }
      ],
      "linkId": "1923091934343",
      "required": true
    },
    {
      "code": [
        {
          "system": "http://loinc.org",
          "code": "8302-2",
          "display": "Body height"
        }
      ],
      "text": "Height",
      "type": "decimal",
      "extension": [
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "[in_us]"
            },
            "display": {
              "unit": "[in_us]"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "cm"
            },
            "display": {
              "unit": "cm"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "m"
            },
            "display": {
              "unit": "m"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[ft_i]",
            "display": "foot"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[in_i]",
            "display": "inch"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[in_i]",
            "display": "inch"
          }
        }
      ],
      "linkId": "6375311029779",
      "initial": [
        {
          "valueDecimal": 0
        }
      ],
      "item": [
        {
          "text": "Height in Inches",
          "type": "display",
          "linkId": "6375311029779_helpText",
          "extension": [
            {
              "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
              "valueCodeableConcept": {
                "text": "Help-Button",
                "coding": [
                  {
                    "code": "help",
                    "display": "Help-Button",
                    "system": "http://hl7.org/fhir/questionnaire-item-control"
                  }
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "code": [
        {
          "system": "http://loinc.org",
          "code": "29463-7",
          "display": "Weight"
        }
      ],
      "text": "Weight",
      "type": "integer",
      "extension": [
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "[lb_av]"
            },
            "display": {
              "unit": "[lb_av]"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": {
              "unit": "kg"
            },
            "display": {
              "unit": "kg"
            }
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[lb_av]",
            "display": "pound"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[lb_av]",
            "display": "pound"
          }
        },
        {
          "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unit",
          "valueCoding": {
            "system": "http://unitsofmeasure.org",
            "code": "[lb_av]",
            "display": "pound"
          }
        }
      ],
      "linkId": "5681920227726",
      "item": [
        {
          "text": "Weight in Pounds",
          "type": "display",
          "linkId": "5681920227726_helpText",
          "extension": [
            {
              "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
              "valueCodeableConcept": {
                "text": "Help-Button",
                "coding": [
                  {
                    "code": "help",
                    "display": "Help-Button",
                    "system": "http://hl7.org/fhir/questionnaire-item-control"
                  }
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "text": "Sleep Habits",
      "linkId": "7830041069695",
      "type": "group",
      "item": [
        {
          "text": "About how many hours do you usually sleep a day?",
          "linkId": "975641938256",
          "type": "decimal",
          "maxLength": 24,
          "extension": [
            {
              "url": "http://hl7.org/fhir/StructureDefinition/maxValue",
              "valueDecimal": 24
            }
          ]
        },
        {
          "text": "What time do you usually go to bed at night",
          "linkId": "5595233028971",
          "type": "time"
        },
        {
          "text": "What time do you usually wake up in the morning",
          "linkId": "9775046682141",
          "type": "time"
        }
      ]
    },
    {
      "text": "Have you ever experienced back pain",
      "linkId": "7507688589592",
      "type": "boolean",
      "initial": [
        {
          "valueBoolean": true
        }
      ],
      "repeats": false,
      "required": true,
      "readOnly": false
    },
    {
      "text": "Back Pain Details",
      "linkId": "6696083212404",
      "type": "group",
      "enableBehavior": "all",
      "enableWhen": [
        {
          "question": "7507688589592",
          "operator": "=",
          "answerBoolean": true
        }
      ],
      "item": [
        {
          "text": "Have you ever taken medication to manage back pain?",
          "linkId": "6506631093455",
          "type": "boolean",
          "item": [
            {
              "text": "Which Medications have you taken?",
              "linkId": "953933492618",
              "type": "open-choice",
              "initial": [
                {
                  "valueCoding": {
                    "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                    "code": "1243440",
                    "display": "Tylenol"
                  }
                }
              ],
              "answerOption": [
                {
                  "valueCoding": {
                    "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                    "code": "1243440",
                    "display": "Tylenol"
                  }
                },
                {
                  "valueCoding": {
                    "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                    "code": "1088953",
                    "display": "Codeine"
                  }
                },
                {
                  "valueCoding": {
                    "display": "Apirin"
                  }
                },
                {
                  "valueCoding": {
                    "display": "Other"
                  }
                }
              ],
              "repeats": true,
              "required": false,
              "enableBehavior": "all",
              "enableWhen": [
                {
                  "question": "6506631093455",
                  "operator": "=",
                  "answerBoolean": true
                }
              ],
              "item": [
                {
                  "text": "List the Other Medications you've taken",
                  "linkId": "498302662737",
                  "type": "string",
                  "enableWhen": [
                    {
                      "question": "953933492618",
                      "operator": "=",
                      "answerCoding": {
                        "display": "Other"
                      }
                    }
                  ]
                }
              ]
            }
          ],
          "enableWhen": [
            {
              "question": "7507688589592",
              "operator": "=",
              "answerBoolean": true
            }
          ]
        },
        {
          "text": "How long has it been since you last experienced back pain",
          "linkId": "4931421371812",
          "type": "choice",
          "answerOption": [
            {
              "valueCoding": {
                "display": "Within the last 2 weeks"
              }
            },
            {
              "valueCoding": {
                "display": "Within the last month"
              }
            },
            {
              "valueCoding": {
                "display": "Within the last year"
              }
            },
            {
              "valueCoding": {
                "display": "I don't remember"
              }
            }
          ],
          "enableWhen": [
            {
              "question": "7507688589592",
              "operator": "=",
              "answerBoolean": true
            }
          ],
          "enableBehavior": "all"
        },
        {
          "code": [
            {
              "system": "http://loinc.org",
              "code": "91348-3",
              "display": "Overall, how bothersome has your back pain been in the last 2 weeks?"
            }
          ],
          "text": "Overall, how bothersome has your back pain been in the last 2 weeks?",
          "answerOption": [
            {
              "valueCoding": {
                "system": "http://loinc.org",
                "code": "LA6568-5",
                "display": "Not at all"
              }
            },
            {
              "valueCoding": {
                "system": "http://loinc.org",
                "code": "LA14454-5",
                "display": "Slightly"
              }
            },
            {
              "valueCoding": {
                "system": "http://loinc.org",
                "code": "LA13939-6",
                "display": "Moderately"
              }
            },
            {
              "valueCoding": {
                "system": "http://loinc.org",
                "code": "LA13914-9",
                "display": "Very much"
              }
            },
            {
              "valueCoding": {
                "system": "http://loinc.org",
                "code": "LA14868-6",
                "display": "Extremely"
              }
            }
          ],
          "type": "choice",
          "linkId": "8557662912930",
          "enableWhen": [
            {
              "question": "4931421371812",
              "operator": "=",
              "answerCoding": {
                "display": "Within the last 2 weeks"
              }
            }
          ]
        }
      ]
    },
    {
      "text": "What day was your last visit with your doctor",
      "linkId": "1967077637018",
      "type": "date",
      "item": [
        {
          "text": "What is your doctor's name",
          "linkId": "6663760446550",
          "type": "text",
          "maxLength": 30
        },
        {
          "text": "Did you visit your doctor for your back pain?",
          "linkId": "4165088966004",
          "type": "boolean",
          "initial": [
            {
              "valueBoolean": false
            }
          ],
          "required": false,
          "enableBehavior": "all",
          "enableWhen": [
            {
              "question": "7507688589592",
              "operator": "=",
              "answerBoolean": true
            },
            {
              "question": "1967077637018",
              "operator": "exists",
              "answerBoolean": true
            }
          ]
        },
        {
          "text": "What is your Doctor or Health System's website",
          "linkId": "8109657622653",
          "type": "url"
        }
      ]
    },
    {
      "text": "Flags (Read Only)",
      "linkId": "3229889426425",
      "type": "group",
      "item": [
        {
          "text": "Senior Citizen?",
          "linkId": "6517365580072",
          "type": "boolean",
          "answerOption": [
            {
              "valueCoding": {
                "display": "Senior Citizen"
              }
            }
          ],
          "enableWhen": [
            {
              "question": "1923091934343",
              "operator": ">",
              "answerInteger": 54
            }
          ],
          "required": false,
          "readOnly": true,
          "initial": [
            {
              "valueBoolean": true
            }
          ]
        },
        {
          "text": "Minor",
          "linkId": "9565403118888",
          "type": "boolean",
          "initial": [
            {
              "valueBoolean": true
            }
          ],
          "readOnly": true,
          "enableWhen": [
            {
              "question": "1923091934343",
              "operator": "<",
              "answerInteger": 18
            }
          ],
          "required": false
        }
      ]
    }
  ]
}

Is this a bug? Am I just misunderstanding something? Can someone who maybe understands this application and schema better than I do help explain what may be happening?

I am able to successfully validate simple and medium-complexity exports against this schema, running into issues with the complex Questionnaire. Other Python JSON schema validators raise the same issue.

Appreciate any and all help :)

akanduru commented 1 year ago

Not sure the problem is with the questionnaire. What is the source of the schema that you are using?

The official schema is available here: https://build.fhir.org/questionnaire.schema.json.html

gularj2 commented 1 year ago

Appreciate the response!

Accidentally left that out of the initial post. I am validating against the full FHIR schema r4 found on this page: https://www.hl7.org/fhir/R4/questionnaire.schema.json.html

image

Looks like that is the same schema found in your project at src/app/assets/fhir.schema.json;

gularj2 commented 1 year ago

If I try and validate against the smaller src/app/assets/fhir-questionnaire.schema.json I get a validation error that is at least easier to understand. My exported Questionnaire has the extension[0].valueCoding['code'] as a dictionary where the schema has it defined as string-only

My Form: image

Snippet From Schema File: image

I don't know if this is helpful information at all but I figured I'd add it

akanduru commented 1 year ago

codeand display should be strings. Is that questionnaire created by this package?

gularj2 commented 1 year ago

Yes, my understanding is that questionnaire was created and exported using the form builder https://lhcformbuilder.nlm.nih.gov/

The Questionnaire JSON I pasted in the initial issue message imports and exports with code and display as dicts

Although, I manually went the questionnaire and removed all the valueCoding instances that had either code or display as dicts and then the questionnaire passes schema validation and imports into the form builder just fine. I spent time just now recreating the questionnaire from scratch and exported it, there were no instances of code or display as dictionaries, and it also passed schema validation. Somehow the questionnaire I was handed was corrupted with those non-conformant valueCoding attributes. I don't know if this was introduced on my side or yours to be honest. Either way the form builder tool accepted and exported the slightly non-conformant questionnaire. Might be a bug ... might be a feature, for you to decide haha

I THINK this can be closed as resolved; Thanks for your help and pointing me towards that smaller questionnaire-only schema, helped me figure out what the actual invalidation was.

akanduru commented 1 year ago

It should probably display some warnings about those errors. I like to keep it open till we address the issue. Thanks for your feed back.