{"record":{"id":"043994b2444258ec","repo":"json-path/JsonPath","slug":"json-assert-error-s-expected-s-actual-s","errorCode":null,"errorMessage":"JSON Assert Error: %s\nExpected:\n%s\nActual:\n%s","messagePattern":"JSON Assert Error: (.+?)\nExpected:\n(.+?)\nActual:\n(.+?)","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java","lineNumber":55,"sourceCode":"            assertionError.initCause(e);\n            throw assertionError;\n        }\n\n        if (!matcher.matches(obj)) {\n\n            throw new AssertionError(String.format(\"JSON path [%s] doesn't match.\\nExpected:\\n%s\\nActual:\\n%s\", path, matcher.toString(), obj));\n        }\n        return this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> JsonAsserter assertThat(String path, Matcher<T> matcher, String message) {\n        T obj = JsonPath.<T>read(jsonObject, path);\n        if (!matcher.matches(obj)) {\n            throw new AssertionError(String.format(\"JSON Assert Error: %s\\nExpected:\\n%s\\nActual:\\n%s\", message, matcher.toString(), obj));\n        }\n        return this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public <T> JsonAsserter assertEquals(String path, T expected) {\n        return assertThat(path, equalTo(expected));\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public JsonAsserter assertNotDefined(String path) {\n\n        try {\n            Configuration c = Configuration.defaultConfiguration();","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path-assert/src/main/java/com/jayway/jsonassert/impl/JsonAsserterImpl.java#L37-L73","documentation":"The message-taking overload of JsonAsserter.assertThat behaves like the plain overload: it reads the path and applies the matcher, throwing AssertionError with the caller-supplied message plus matcher and actual value when the matcher fails. The custom message is purely descriptive context; the root cause is a matcher mismatch.","triggerScenarios":"JsonAssert.with(json).assertThat(\"$.items.size()\", hasSize(3), \"expected 3 items\") — any call where matcher.matches(obj) returns false, with the message parameter supplied.","commonSituations":"Test suites that add business-readable messages to JSON assertions, then fail after an upstream API or fixture changes; commonly seen when asserting computed values like .length() or .size().","solutions":["Read the 'Expected'/'Actual' sections of the AssertionError to identify the mismatch.","Re-run JsonPath.read on the path to inspect the live value.","Update the matcher/expected value or the JSON fixture to the correct state.","Adjust the custom message if it no longer accurately describes the assertion."],"exampleFix":"// before\nwith(json).assertThat(\"$.count\", equalTo(2), \"count must be 2\");\n// after\nint actual = JsonPath.read(json, \"$.count\");\nwith(json).assertThat(\"$.count\", equalTo(actual), \"count must match fixture\");","handlingStrategy":"validation","validationCode":"T actual = JsonPath.<T>read(jsonObject, path);\nif (!matcher.matches(actual)) throw new AssertionError(message + \" | actual=\" + actual);","typeGuard":null,"tryCatchPattern":"try {\n    with(json).assertThat(path, matcher, message);\n} catch (AssertionError e) {\n    log.error(\"JSON assert failed: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["Keep the custom message synchronized with the matcher.","Prefer explicit JsonPath.read for debugging mismatches.","Pin fixtures in version control and update them via reviewed diffs."],"tags":["json","assertion","testing","hamcrest"],"backgroundTag":"schema-validation-failed","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}