{"id":36419262,"url":"https://github.com/unbroken-dome/jackson-bean-validation","last_synced_at":"2026-01-11T17:02:34.883Z","repository":{"id":45931313,"uuid":"168015714","full_name":"unbroken-dome/jackson-bean-validation","owner":"unbroken-dome","description":"A Jackson module that performs Java Bean Validation during deserialization.","archived":false,"fork":false,"pushed_at":"2022-12-15T09:03:24.000Z","size":188,"stargazers_count":20,"open_issues_count":6,"forks_count":12,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-10-31T10:51:58.484Z","etag":null,"topics":["bean-validation","jackson","json","json-validation","validation"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unbroken-dome.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-28T18:43:30.000Z","updated_at":"2023-09-18T06:59:10.000Z","dependencies_parsed_at":"2022-09-06T23:31:07.103Z","dependency_job_id":null,"html_url":"https://github.com/unbroken-dome/jackson-bean-validation","commit_stats":null,"previous_names":[],"tags_count":5,"template":null,"template_full_name":null,"purl":"pkg:github/unbroken-dome/jackson-bean-validation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbroken-dome%2Fjackson-bean-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbroken-dome%2Fjackson-bean-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbroken-dome%2Fjackson-bean-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbroken-dome%2Fjackson-bean-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unbroken-dome","download_url":"https://codeload.github.com/unbroken-dome/jackson-bean-validation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbroken-dome%2Fjackson-bean-validation/sbom","scorecard":{"id":908916,"data":{"date":"2025-08-11","repo":{"name":"github.com/unbroken-dome/jackson-bean-validation","commit":"7ff9d68a31d0aab907509279b972a49bd7f49e0f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 1/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 14 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T18:24:27.532Z","repository_id":45931313,"created_at":"2025-08-24T18:24:27.532Z","updated_at":"2025-08-24T18:24:27.532Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bean-validation","jackson","json","json-validation","validation"],"created_at":"2026-01-11T17:02:34.810Z","updated_at":"2026-01-11T17:02:34.871Z","avatar_url":"https://github.com/unbroken-dome.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Jackson Bean Validation Module\n:version: 0.6.0\n:groupId: org.unbroken-dome.jackson-bean-validation\n:artifactId: jackson-bean-validation\n\nimage:https://img.shields.io/maven-central/v/{groupId}/{artifactId}[]\n\nThis is a https://github.com/FasterXML/jackson[Jackson] extension to perform\nhttps://beanvalidation.org/2.0/[Java Bean Validation] during deserialization.\n\n== The Problem\n\nThis module is aimed mostly at REST APIs that should validate incoming JSON request\nbodies, but it may be useful in other scenarios.\n\nImagine the following JSON request body:\n\n[source,json]\n----\n{\n    \"firstName\": \"John\",\n    \"lastName\": \"Doe\",\n    \"dateOfBirth\": \"1983-01-25\"\n}\n----\n\nIn application code, This might be mapped to the following Java class with Jackson\nand validation constraints:\n\n[source,java]\n----\npublic class PersonRequest {\n\n    @NotEmpty\n    String firstName;\n\n    @NotEmpty\n    String lastName;\n\n    @Past\n    LocalDate dateOfBirth; // requires JavaTimeModule\n\n    // Getters and setters omitted\n}\n----\n\nThis works in the success case, but there could be a number of things that are wrong\nabout the request (assuming that it is syntactically correct JSON):\n\n* Any of the properties might be missing.\n* Any of the properties might have a wrong type in JSON (e.g. a `boolean`)\n* The `dateOfBirth` might be in a format that is not parseable to a `LocalDate`.\n* Any of the validation constraints might be violated.\n\nAll of these cases are typically handled by sending a `400 Bad Request` response back to the client,\nideally with a description of _all_ that was wrong with the request. This is especially important if such\nerrors should be displayed on a form in a UI.\n\nIn application code, this is most often handled with a two-step process:\n\n. Deserialize the JSON payload into the Java object.\n. Run the Bean `Validator` on it to find any constraint violations.\n\nThe big problem is that if step 1 fails (for example because `dateOfBirth` was not parseable to a `LocalDate`),\nJackson will throw an exception, and the response will only contain that single error information. Also, from the\nJackson exception it can be hard to pinpoint the exact property in the request that had a bad value. The client\nwill have to fix that one error and try again, only to find out that there are more errors that had not been reported\nearlier.\n\nFor example, with the following request:\n\n[source,json]\n----\n{\n    \"firstName\": \"\",\n    \"dateOfBirth\": \"01-25\"\n}\n----\n\nThis should ideally return a `400 Bad Request` response informing about 3 violations (`firstName` must not be empty,\n`lastName` is missing, and `dateOfBirth` has a wrong format). However, since Jackson throws a `MismatchedInputException`\non parsing the `dateOfBirth`, the client won't even get to see the `firstName` and `lastName` violations until they try\nagain with a correct `dateOfBirth`.\n\nObviously, the only solution to this is to merge steps 1 and 2 into one, and perform the validation immediately\n_during_ deserialization. This is where this module comes in.\n\n\n== Usage\n\nThe module library is available on\nhttps://search.maven.org/artifact/org.unbroken-dome.jackson-bean-validation/jackson-bean-validation/{version}/bundle[Maven Central].\n\nAdd the following dependency to your build script:\n\n[source,groovy,subs=\"+attributes\"]\n.Gradle (build.gradle)\n----\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation 'org.unbroken-dome.jackson-bean-validation:jackson-bean-validation:{version}'\n}\n----\n\n[source,xml,subs=\"+attributes\"]\n.Maven (pom.xml)\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.unbroken-dome.jackson-bean-validation\u003c/groupId\u003e\n    \u003cartifactId\u003ejackson-bean-validation\u003c/artifactId\u003e\n    \u003cversion\u003e{version}\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nIn Java code, register an instance `BeanValidationModule` with your `ObjectMapper`. It also\nrequires a `ValidatorFactory` instance for performing validation. (For example,\nhttp://hibernate.org/validator/[Hibernate Validator] is a widespread implementation of Bean Validation).\n\n[source,java]\n----\n\nValidatorFactory validatorFactory = Validation.byDefaultProvider()\n    .configure()\n    .buildValidatorFactory();\n\nBeanValidationModule module = new BeanValidationModule(validatorFactory);\n\nObjectMapper objectMapper = new ObjectMapper()\n    .registerModule(module);\n----\n\n\nAnnotate all classes that should be validated with `@JsonValidated`. If this annotation is not\npresent, no validation will be performed.\n\n[source,java]\n----\n@JsonValidated\npublic class PersonRequest {\n\n    @NotEmpty\n    String firstName;\n\n    @NotEmpty\n    String lastName;\n\n    @Past\n    LocalDate dateOfBirth;\n\n    // Getters and setters omitted\n}\n----\n\nTo cascade the bean validation to nested beans, you can also annotate the property or constructor parameter\nwith `@Valid`.\n\n[source,java]\n----\n@JsonValidated\npublic class PersonRequest {\n\n    static class Name {\n        @NotEmpty String firstName;\n        @NotEmpty String lastName;\n    }\n\n    @Valid Name name;\n}\n----\n\n\n== Handling Violations\n\nDeserialization of this object, with the `BeanValidationModule` activated, might now throw a\n`ConstraintViolationException` that contains _all_ the violations of the input document, including JSON\ndeserialization issues as well as constraint violations.\n\n\n[NOTE]\n.Property Paths\n====\nAll property paths in the `ConstraintViolation` objects refer to the property names in the input JSON, _not_\nthe Java bean property names. They might be different if you use `@JsonNaming` with a custom name mapping strategy,\nor `@JsonProperty` with explicit names.\n\nThe reason for this is that we're conceptually validating the JSON object and not the Java bean (which is just being\nconstructed).\n====\n\n\nTo deal with errors that would otherwise result in exceptions thrown by Jackson, the module introduces two \"pseudo\"\nconstraints that are used for reporting these as constraint violations (even if they are not placed on the properties).\n\n\n=== `JsonValidInput`\n\nThe module introduces a pseudo-constraint `JsonValidInput` that will be reported as violated whenever Jackson\nwould otherwise throw a `MismatchedInputException`.\n\nIn the above examples, a value for `dateOfBirth` that cannot be parsed to a `LocalDate` would be reported as a\nviolation of the `JsonValidInput` constraint, including the path to that property.\n\nYou can also place `@JsonValidValue` directly on a property in case you want a customized validation message:\n\n[source,java]\n----\n@JsonValidValue(message = \"Please enter a date in the format YYYY-MM-DD\")\n@Past\nLocalDate dateOfBirth;\n----\n\nNote that `@JsonValidValue` is not an actual constraint annotation (it is not meta-annotated with `@Constraint`);\nplacing it on a property is only for customization of the constraint parameters.\n\n\n=== `JsonRequired`\n\nThe second pseudo-constraint is `JsonRequired`; it is violated if there are any _missing_ properties that\nare marked as required using the `@JsonProperty` annotation:\n\n[source,java]\n----\npublic class PersonRequest {\n\n    @JsonCreator\n    public PersonRequest(\n        @JsonProperty(value=\"firstName\", required=true) String firstName\n        @JsonProperty(value=\"lastName\", required=true) String lastName,\n        @JsonProperty(value=\"dateOfBirth\") LocalDate dateOfBirth) {\n        // ...\n    }\n}\n----\n\nIn this example, if `firstName` and/or `lastName` are missing in the input, they would be reported as a violation\nto `JsonRequired`.\n\nNOTE: `JsonRequired` violations are not triggered if the value is present in the JSON input but explicitly set to\n`null`. Use the standard `@NotNull` constraint to catch this case.\n\nAgain, you could place `@JsonRequired` directly on a property; this has the same effect as\n`@JsonProperty(required = true)` but also allows you to customize the validation message.\n\n\n=== Customizing Validation Messages\n\nFor `JsonValidInput` and `JsonRequired`, there are three ways to provide validation messages (in order of precedence):\n\n* *Property level*: Put the annotation directly on the validated property, and set its `message` argument\n  (as described above).\n\n* *Class level*: Set the `validInputMessage` or `requiredMessage` on the `@JsonValidated` annotation:\n+\n[source,java]\n----\n@JsonValidated(\n    validInputMessage=\"is not valid\",\n    requiredMessage=\"is required\")\npublic class PersonRequest {\n    // ...\n}\n----\n\n* *Global level*: Put the messages in your `ValidationMessages.properties` (or locale-specific variants):\n+\n[source,java-properties]\n.ValidationMessages.properties\n----\norg.unbrokendome.jackson.beanvalidation.JsonValidInput.message=is not valid\norg.unbrokendome.jackson.beanvalidation.JsonRequired.message=is required\n----\n+\nNote that the global messages should _always_ be configured; the module library cannot provide defaults because\nthere cannot be a second `ValidationMessages.properties` on the classpath.\n\n\n=== Cross-Parameter Validation with `@AssertTrue`\n\n`@AssertTrue` constraints on instance methods are a common pattern with Bean Validation to perform cross-parameter\nvalidation. With the bean validation module, this may not work as intended because the properties are validated\nindependently as they are deserialized, and the bean will not even be constructed if any of the property values\nviolates the constraints.\n\nTo enable evaluation of an `@AssertTrue` constraint, enable the `BeanValidationFeature.VALIDATE_BEAN_AFTER_CONSTRUCTION`\nfeature flag, which will cause the bean to be validated as a whole after it is fully constructed. Even so, such a\nviolation will only be reported if the bean _can_ be constructed, so a violation may not be visible if there\nare other violations on creator properties (i.e. constructor params).\n\n\n== Kotlin Support\n\nThe module should work well with Kotlin, and together with the `KotlinModule` from `jackson-module-kotlin`.\nI would recommend to always use `data` classes where all properties are initialized in the constructor.\n\nIt is especially useful to perform `NotNull` checks on constructor arguments that are _not_ nullable in Kotlin,\nbecause the validation happens before the constructor is called:\n\n[source,kotlin]\n----\n@JsonValidated\ndata class PersonRequest(\n    @param:NotNull val firstName: String,\n    @param:NotNull val lastName: String,\n    @param:Past val dateOfBirth: LocalDate)\n----\n\nThe validating deserializer will automatically detect nullability of constructor parameter types, and treat the\nparameters with non-nullable types as if they had an implicit `@NotNull` annotation. So the following is equivalent\nto the example above:\n\n[source,kotlin]\n----\n@JsonValidated\ndata class PersonRequest(\n    val firstName: String,\n    val lastName: String,\n    @param:Past val dateOfBirth: LocalDate)\n----\n\nSo, you no longer need to use `String?` just to validate `@NotNull` and use those ugly double exclamation\nmarks everywhere.\n\n[INFO]\n====\nRemember that annotations on `val` parameters in the constructor should be qualified with `@param:`. You can place\nmultiple constraints with the shorthand syntax e.g. `@param:[NotNull Size(min = 3)]`.\n====\n\n=== Handling of Required Parameters and Primitives\n\nThe standard `KotlinModule` automatically treats all constructor parameters as required if they are not marked as\nnullable (e.g. `String` instead of `String?`). If such parameters are missing in the JSON input, a violation of\n`JsonRequired` would be raised.\n\nHowever, for primitive types this behavior only applies if the deserialization feature `FAIL_ON_NULL_FOR_PRIMITIVES`\nis enabled (it is disabled by default). Otherwise, `null` or missing values are mapped to the default value of the\ntype (e.g. `0` for integers) even if the type is not nullable.\n\nI would recommend enabling `FAIL_ON_NULL_FOR_PRIMITIVES` when using Kotlin together with this module.\n\n\n=== Late-init Properties\n\nKotlin's `lateinit var` properties are deserialized like other properties, and their values will be validated based on\nthe annotations on the property. In addition, `lateinit var` properties are treated as if they had an implicit\n`NotNull` constraint, because they cannot have nullable or primitive types. An explicit `@NotNull` annotation will\nstill be honored if present (for example, to customize the validation message).\n\n- If the input JSON contains an explicit `null` value for the property, it will always be considered a violation of\n  the `NotNull` constraint.\n- If the input JSON does not contain the property at all, it will be considered a violation of `NotNull` by default,\n  but this behavior can be controlled with the `BeanValidationFeature.VALIDATE_KOTLIN_LATEINIT_VARS` feature flag.\n  You may want to switch off this behavior if you intend to initialize the `lateinit var` properties programmatically\n  after deserialization.\n\n\n== Jackson Version Compatibility\n\nThe module requires Jackson 2.9.x or higher. It does not work with Jackson 2.8.x.\n\nAutomated compatibility tests are run for the following Jackson versions:\n\n|===\n| Jackson major/minor | Tested compatibility\n\n| 2.9 | 2.9.0 -- 2.9.10\n| 2.10 | 2.10.0 -- 2.10.5\n| 2.11 | 2.11.0 -- 2.11.4\n| 2.12 | 2.12.0 -- 2.12.3\n|===\n\n\n== Limitations and Considerations\n\n* Jackson handles a plethora of corner-cases and custom annotations, and probably many of them are not working\n  properly. The module _should_ work for the most common cases (vanilla beans or constructor properties). If you\n  spot an error with one of the more obscure Jackson features, please consider filing an issue.\n\n* Jackson views are currently not supported (they might just work, but lacking more extensive testing).\n\n* Validation groups are currently not supported - mostly because there is no nice way of passing them to the\n  `ObjectMapper` when deserializing.\n\n* Bean validation does not allow parameter validation on static methods. That means that static `@JsonCreator` factory\n  methods will only be checked for valid input and required parameters, but actual bean validation constraints on\n  these parameters will not be evaluated.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbroken-dome%2Fjackson-bean-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funbroken-dome%2Fjackson-bean-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbroken-dome%2Fjackson-bean-validation/lists"}