Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
gularj2 opened this issue May 23, 2023 · 6 comments

Comments

@gularj2
Copy link

gularj2 commented May 23, 2023

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:

  • message:
"Additional properties are not allowed ('enableWhen', 'type' were unexpected)"
  • the invalid object
{
  "text": "List the Other Medications you've taken",
  "linkId": "498302662737",
  "type": "string",
  "enableWhen": [
    {
      "question": "953933492618",
      "operator": "=",
      "answerCoding": {
        "display": "Other"
      }
    }
  ]
}
  • schema being referenced (seems like QuestionnaireResponse_Item is being referenced somehow when it should still be QuestionnaireItem?)
{
  "additionalProperties": false,
  "description": "A structured set of questions and their answers. The questions are ordered and grouped into coherent subsets, corresponding to the structure of the grouping of the questionnaire being responded to.",
  "properties": {
    "_definition": {
      "$ref": "#/definitions/Element",
      "description": "Extensions for definition"
    },
    "_linkId": {
      "$ref": "#/definitions/Element",
      "description": "Extensions for linkId"
    },
    "_text": {
      "$ref": "#/definitions/Element",
      "description": "Extensions for text"
    },
    "answer": {
      "description": "The respondent's answer(s) to the question.",
      "items": {
        "$ref": "#/definitions/QuestionnaireResponse_Answer"
      },
      "type": "array"
    },
    "definition": {
      "$ref": "#/definitions/uri",
      "description": "A reference to an [[[ElementDefinition]]] that provides the details for the item."
    },
    "extension": {
      "description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance  applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
      "items": {
        "$ref": "#/definitions/Extension"
      },
      "type": "array"
    },
    "id": {
      "$ref": "#/definitions/string",
      "description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces."
    },
    "item": {
      "description": "Questions or sub-groups nested beneath a question or group.",
      "items": {
        "$ref": "#/definitions/QuestionnaireResponse_Item"
      },
      "type": "array"
    },
    "linkId": {
      "$ref": "#/definitions/string",
      "description": "The item from the Questionnaire that corresponds to this item in the QuestionnaireResponse resource."
    },
    "modifierExtension": {
      "description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element's descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
      "items": {
        "$ref": "#/definitions/Extension"
      },
      "type": "array"
    },
    "text": {
      "$ref": "#/definitions/string",
      "description": "Text that is displayed above the contents of the group or as the text of the question being answered."
    }
  }
}

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
Copy link
Collaborator

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
Copy link
Author

gularj2 commented May 23, 2023

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
Copy link
Author

gularj2 commented May 23, 2023

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
Copy link
Collaborator

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

@gularj2
Copy link
Author

gularj2 commented May 23, 2023

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
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants