diff --git a/odp-core/src/main/java/org/offeringprotocol/odp/core/OdpJson.java b/odp-core/src/main/java/org/offeringprotocol/odp/core/OdpJson.java index 7a467fd..f576367 100644 --- a/odp-core/src/main/java/org/offeringprotocol/odp/core/OdpJson.java +++ b/odp-core/src/main/java/org/offeringprotocol/odp/core/OdpJson.java @@ -403,7 +403,13 @@ public static Offering parseOffering(String json) { } public static ProblemDetails parseProblemDetails(String json) { - return parse(json, "problem-details.schema.json", "Problem Details", ProblemDetails.class); + ProblemDetails problem = parse(json, "problem-details.schema.json", "Problem Details", ProblemDetails.class); + String expectedType = "https://offeringprotocol.org/problems/" + + problem.code().toLowerCase(Locale.ROOT).replace('_', '-'); + if (!expectedType.equals(problem.type())) { + throw semanticError("Problem Details", "type must correspond to the problem code", "/type"); + } + return problem; } public static SearchRequests.Collections parseCollectionSearchRequest(String json) { diff --git a/odp-json-jackson3/src/test/java/org/offeringprotocol/odp/core/OdpJsonTest.java b/odp-json-jackson3/src/test/java/org/offeringprotocol/odp/core/OdpJsonTest.java index 513428a..49fbfad 100644 --- a/odp-json-jackson3/src/test/java/org/offeringprotocol/odp/core/OdpJsonTest.java +++ b/odp-json-jackson3/src/test/java/org/offeringprotocol/odp/core/OdpJsonTest.java @@ -121,6 +121,20 @@ void rejectsInvalidServiceDocuments() { assertTrue(!exception.issues().isEmpty()); } + @Test + void rejectsProblemTypesThatDoNotCorrespondToTheCode() { + String problem = """ + { + "code":"NOT_FOUND", + "status":404, + "title":"Not found", + "type":"https://offeringprotocol.org/problems/validation-failed" + } + """; + + assertThrows(OdpValidationException.class, () -> OdpJson.parseProblemDetails(problem)); + } + @Test void enforcesServiceDocumentSemanticConstraints() { String duplicateLocalization =