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

FHIR server $validate accepts resource json with duplicate keys #1155

Closed
mjdisc opened this issue May 27, 2020 · 16 comments
Closed

FHIR server $validate accepts resource json with duplicate keys #1155

mjdisc opened this issue May 27, 2020 · 16 comments
Assignees
Labels
bug Something isn't working

Comments

@mjdisc
Copy link
Contributor

mjdisc commented May 27, 2020

During initial PDM R6.0 testing, it was discovered that a FHIR $validate operation would return a NoError response for a resource with duplicate keys. This can be reproduced as follows:

url: https://us-south.wh-fhir.dev.cloud.ibm.com/wh-fhir-dev/api/v4//Condition/$validate

POST payload:

{
	"resourceType": "Condition",
	"subject": {
		"reference": "Patient/b589c393-4146-4fef-921d-3facbfbd3bd0"
	},
	"subject": {
		"reference": "Patient/e8f4d046-4eb5-4c9e-972a-fb02c5e4d5f4"
	}
}

Strictly speaking, the json spec allows duplicate keys. But many json editors and other tooling flag dup keys as an error. I then sent the above resource to the create API. The Condition was successfully created, with the second subject only.

I think it would be prudent for FHIR to detect duplicate keys on resources and return the appropriate failure responses on validate, create, update. Persisting data in the FHIR database that passed validation and yet is not a reflection of the data sent in by the user is misleading, IMHO.

@mjdisc mjdisc added the bug Something isn't working label May 27, 2020
@JohnTimm JohnTimm self-assigned this May 27, 2020
@prb112 prb112 added this to the Sprint 13 milestone May 27, 2020
@JohnTimm
Copy link
Collaborator

I was able to reproduce this with the following unit test:

    @Test
    public void testDuplicateKeys() throws Exception {
        try (InputStream in = DuplicateKeysTest.class.getClassLoader().getResourceAsStream("JSON/condition-duplicate-keys.json")) {
            JsonReader jsonReader = Json.createReader(in);
            JsonObject jsonObject = jsonReader.readObject();
            System.out.println(jsonObject);
        }
    }

This indicates that the underlying javax.json library has a bug. I will investigate a mitigation strategy.

@JohnTimm
Copy link
Collaborator

JohnTimm commented May 27, 2020

According to this stack overflow, the JSON spec doesn't explicitly forbid duplicate keys:
https://stackoverflow.com/questions/21832701/does-json-syntax-allow-duplicate-keys-in-an-object

Even the org.json parser allows duplicate keys by default and requires a source code modification to mitigate:
https://medium.com/@harshalparekh20696/modifying-org-json-to-handle-duplicate-keys-975bfffe2f5a

https://cyantificmusings.wordpress.com/2016/05/16/duplicate-keys-in-json-objects/

@JohnTimm
Copy link
Collaborator

In order to mitigate this issue, we would need to either: a) implore the javax.json folks to fix their implementation, b) switch to a different JSON library that rejects duplicates or c) write our own JSON parser.

@lmsurpre
Copy link
Member

from https://www.hl7.org/fhir/json.html

Property names SHALL be unique. Note: this is not explicitly stated in the original JSON specification,so stated for clarity here

So it would be nice to have a longer-term plan for this one. Maybe start by just opening an issue at https://github.com/eclipse-ee4j/jsonp/issues to see if they would consider adding it as an option?

@JohnTimm
Copy link
Collaborator

I tried swapping out the javax.json implementation with: https://github.com/leadpony/joy and, unfortunately, it has the exact same behavior.

@JohnTimm
Copy link
Collaborator

JohnTimm commented May 27, 2020

Jackson exhibits the same behavior using this code:

    @Test
    public void testDuplicateKeys2() throws Exception {
        try (InputStream in = DuplicateKeysTest.class.getClassLoader().getResourceAsStream("JSON/condition-duplicate-keys.json")) {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readValue(in, JsonNode.class);
            System.out.println(jsonNode);
        }
    }

@JohnTimm
Copy link
Collaborator

Found an option to prohibit duplicate keys:

    @Test
    public void testDuplicateKeys2() throws Exception {
        try (InputStream in = DuplicateKeysTest.class.getClassLoader().getResourceAsStream("JSON/condition-duplicate-keys.json")) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
            JsonNode jsonNode = objectMapper.readValue(in, JsonNode.class);
            System.out.println(jsonNode);
        }
    }

@JohnTimm
Copy link
Collaborator

JohnTimm commented May 27, 2020

#After further research, I found that Jackson supports a configuration that will reject duplicate keys:

    @Test
    public void testDuplicateKeys2() throws Exception {
        try (InputStream in = DuplicateKeysTest.class.getClassLoader().getResourceAsStream("JSON/condition-duplicate-keys.json")) {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.enable(JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
            JsonNode jsonNode = objectMapper.readValue(in, JsonNode.class);
            System.out.println(jsonNode);
        }
    }

Jackson also has compatibility with javax.json:
https://github.com/FasterXML/jackson-datatypes-misc/tree/master/jsr-353

This module implements the javax.json object model on top of Jackson. I worked out a way that we could wire this up in the fhir-provider module. It fixes the original issue, but introduces a new issue related to BigDecimal precision. Precision in does not always equal precision out. In order to fix the precision issue, I would need to modify a source file coming from the Jackson project. This doesn't seem like a viable solution. We have raised an issue with the jakarta-ee JSON-P project here:

jakartaee/jsonp-api#240

They said that they would welcome a PR to fix the issue directly in their codebase.

@JohnTimm
Copy link
Collaborator

Created this PR:
jakartaee/jsonp-api#241

@lmsurpre lmsurpre removed this from the Sprint 13 milestone Jun 19, 2020
@prb112
Copy link
Contributor

prb112 commented Apr 7, 2021

John mentioned his PR is now accepted. We are awaiting the next release

@lmsurpre lmsurpre added this to the Sprint 2021-08 milestone Jun 1, 2021
JohnTimm added a commit that referenced this issue Jun 1, 2021
Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
JohnTimm added a commit that referenced this issue Jun 1, 2021
Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
JohnTimm added a commit that referenced this issue Jun 1, 2021
Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
JohnTimm added a commit that referenced this issue Jun 1, 2021
Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
JohnTimm added a commit that referenced this issue Jun 2, 2021
* Issue #1155 - upgrade to jakarta.json 2.0.1

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>

* Issue #1155 - removed workaround, added unit test

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>

* Issue #1155 - updated bulkdata operation unit test

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
@prb112
Copy link
Contributor

prb112 commented Jun 3, 2021

Reviewing results for QA with John. Sent him a postman collection to confirm the behavior

@prb112
Copy link
Contributor

prb112 commented Jun 3, 2021

Discussed with John.

Nested Objects and Arrays result in an unintended result where duplicate keys are ignored.

The postman collection is at https://gist.github.com/prb112/9b1d73bcd606507df393aa497b64ae8c

@JohnTimm
Copy link
Collaborator

JohnTimm commented Jun 3, 2021

I created this issue in the the eclipse-ee4j/jsonp GitHub issue tracker:
jakartaee/jsonp-api#292

then I created this PR:
jakartaee/jsonp-api#293

which was immediately reviewed and merged into master. This fix should be part of their next patch release.

tbieste pushed a commit that referenced this issue Jun 9, 2021
* Issue #1155 - upgrade to jakarta.json 2.0.1

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>

* Issue #1155 - removed workaround, added unit test

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>

* Issue #1155 - updated bulkdata operation unit test

Signed-off-by: John T.E. Timm <johntimm@us.ibm.com>
@lmsurpre lmsurpre removed this from the Sprint 2021-09 milestone Jul 7, 2021
prb112 added a commit that referenced this issue Sep 22, 2021
Signed-off-by: Paul Bastide <pbastide@us.ibm.com>
@prb112
Copy link
Contributor

prb112 commented Sep 22, 2021

PR #2794 moves to parrson groupId and project. It's still part of Eclipse and has John's fix in it.

@prb112 prb112 self-assigned this Sep 22, 2021
@prb112
Copy link
Contributor

prb112 commented Sep 22, 2021

PR is raised, and just needs QA

lmsurpre added a commit that referenced this issue Sep 22, 2021
Update for #1155 and move to parsson
@prb112
Copy link
Contributor

prb112 commented Oct 1, 2021

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "fatal",
            "code": "invalid",
            "details": {
                "text": "FHIRProvider: Duplicate key &#39;status&#39; is not allowed"
            },
            "expression": [
                "<no expression>"
            ]
        }
    ]
}

Test passes now as expected and rejects nested duplication in the Bundle, contained and nested JSON objects

@prb112 prb112 closed this as completed Oct 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants