{"id":36602192,"url":"https://github.com/exabrial/form-binding","last_synced_at":"2026-01-12T08:39:32.787Z","repository":{"id":144519975,"uuid":"221564194","full_name":"exabrial/form-binding","owner":"exabrial","description":"Bind Java objects to URL Encoded Forms similar to JSON-B or JAX-B, and a JAX-RS Form Encoding MessageBodyWriter/Reader","archived":false,"fork":false,"pushed_at":"2025-05-28T18:07:19.000Z","size":77,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-05T11:16:51.895Z","etag":null,"topics":["annotations","binding","converter","encoding","form","http","java","java-ee","java-spi","jax-rs","parameters","rest","url-encoding","x-www-form-urlencoded"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exabrial.png","metadata":{"files":{"readme":"README.md","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-13T22:32:50.000Z","updated_at":"2024-05-29T22:12:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"3ae2700c-603d-4fa3-b1aa-d3a0023cab7f","html_url":"https://github.com/exabrial/form-binding","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/exabrial/form-binding","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exabrial%2Fform-binding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exabrial%2Fform-binding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exabrial%2Fform-binding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exabrial%2Fform-binding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exabrial","download_url":"https://codeload.github.com/exabrial/form-binding/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exabrial%2Fform-binding/sbom","scorecard":{"id":387516,"data":{"date":"2025-08-11","repo":{"name":"github.com/exabrial/form-binding","commit":"3de3833b3704fb5dc24e3e02dd289efa21f0105a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"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":"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":"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":"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":"Code-Review","score":0,"reason":"Found 0/25 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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: 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":8,"reason":"3 out of the last 3 releases have a total of 3 signed artifacts.","details":["Info: signed release artifact: form-binding-1.2.0-sources.jar.asc: https://github.com/exabrial/form-binding/releases/tag/form-binding-1.2.0","Info: signed release artifact: form-binding-1.1.0-javadoc.jar.asc: https://github.com/exabrial/form-binding/releases/tag/form-binding-1.1.0","Info: signed release artifact: form-binding-1.0.0-sources.jar.asc: https://github.com/exabrial/form-binding/releases/tag/form-binding-1.0.0","Warn: release artifact form-binding-1.2.0 does not have provenance: https://api.github.com/repos/exabrial/form-binding/releases/21976044","Warn: release artifact form-binding-1.1.0 does not have provenance: https://api.github.com/repos/exabrial/form-binding/releases/21745069","Warn: release artifact form-binding-1.0.0 does not have provenance: https://api.github.com/repos/exabrial/form-binding/releases/21490323"],"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":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-wxr5-93ph-8wr9"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T16:59:51.597Z","repository_id":144519975,"created_at":"2025-08-18T16:59:51.597Z","updated_at":"2025-08-18T16:59:51.597Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28337599,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["annotations","binding","converter","encoding","form","http","java","java-ee","java-spi","jax-rs","parameters","rest","url-encoding","x-www-form-urlencoded"],"created_at":"2026-01-12T08:39:32.123Z","updated_at":"2026-01-12T08:39:32.780Z","avatar_url":"https://github.com/exabrial.png","language":"Java","readme":"# Form Binding\n\nI looked far and wide and was surprised that there was no annotation based way to bind Form URL Encoded string to a Java Object. Think of this project like JAX-B or JSON-B, but for Form URL Encoding.\n\nWouldn't it be nice to create this form:\n\n```\nkey=AGreatSuccess\u0026anInt=42\n```\n\nFrom this object:\n\n```\npublic class TestObject {\n\tprivate String key = \"AGreatSuccess\";\n\tprivate int anInt = 42;\n}\n```\n\nWith on line of code:\n\n```\nfinal String form = writer.write(new TestObject());\n```\n\nYes. Yes it would. Oh and there's a JAX-RS integration: MessageBodyReader and MessageBodyWriter that produces/consumes `application/x-www-form-urlencoded`!\n\n\n## License\nAll files are Licensed Apache Source License 2.0. Please consider contributing back any changes you may make, thanks!\n\n## Usage\n\nThere are two parts, and API jar and a implementation jar. Include the API jar in your project as a compile dependency, and the implementation jar as a runtime dependency. Annotate your fields (or don't, the default behavior uses the field name and looks at any fields not marked as transient). The Java SPI system will load the implementation for you. \n\nInternally this project makes heavy use of Apache Bean Utils `ConvertUtils` to convert between strings and value types. You can even extend this behavior by implementing `FormBindingConverter` and packaging it as a Java SPI Service.\n\n### Maven Coordinates\n\n\nAPI Jar:\n\n```\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.exabrial\u003c/groupId\u003e\n\t\u003cartifactId\u003eform-binding-api\u003c/artifactId\u003e\n\t\u003cversion\u003eSEE THE RELEASES TAB FOR VERSION NUMBER\u003c/version\u003e\n\t\u003cscope\u003ecompile\u003c/scope\u003e\n\u003c/dependency\u003e\n```\nRuntime Jar:\n\n```\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.exabrial\u003c/groupId\u003e\n\t\u003cartifactId\u003eform-binding\u003c/artifactId\u003e\n\t\u003cversion\u003eSEE THE RELEASES TAB FOR VERSION NUMBER\u003c/version\u003e\n\t\u003cscope\u003eruntime\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n### Binding your classes\n\n* The default behavior is to bind all of your fields that are not marked `@FormBindingTransient`\n* If _any_ field is marked as a `@FormBindingParam`, only fields that are marked with `@FormBindingParam` will be serialized\n* You can change the name of the parameter bound like this: `@FormBindingParam(paramName = \"differentName\")`\n\nExample:\n\n```\npublic class MixedAnnotations {\n\t@FormBindingParam(paramName = \"differentName\")\n\tprivate String heresAField = \"Here's a field!!!\";\n\t@FormBindingTransient\n\tprivate String ignoreMe = \"Don't encode this!!\";\n\tprivate String heresANonAnnotatedField = \"It shouldn't be included\";\n}\n```\n\n### Java Object -\u003e Form URL Encoded String\n\n\n```\nFormBindingWriter writer = FormBinding.getWriter();\nString form = writer.write(new MixedAnnotations());\n```\n\nWill produce:\n\n```\ndifferentName=Here%27s+a+field%21%21%21\n```\n\n### Form URL Encoded String -\u003e Java Object\n\n```\nString input = \"differentName=ConvertingBackToJavaObject\";\nMixedAnnotations mixedAnnotations = reader.read(input, MixedAnnotations.class);\n```\n\nOn the returned object, `heresAField` the field will be set to: `ConvertingBackToJavaObject`\n\n\n### Implementing your own converter\n\n* Bean Utils does pretty good job with basic types, but if you have nested objects, you'll want to implement your own converter.\n* Simply implement that `FormBindingConverter` interface, then put a file in `META-INF/services` named `com.github.exabrial.formbinding.FormBindingConverter`\n* Inside this file, put the fully qualified classname of your custom implementation\n* See https://github.com/exabrial/form-binding/tree/master/form-binding-test-module for an example\n\n\n### JAX-RS\n\n\n#### Maven Coordinates\n\n```\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.exabrial\u003c/groupId\u003e\n\t\u003cartifactId\u003eform-binding-jaxrs\u003c/artifactId\u003e\n\t\u003cversion\u003eSEE THE RELEASES TAB FOR VERSION NUMBER\u003c/version\u003e\n\t\u003cscope\u003ecompile\u003c/scope\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecom.github.exabrial\u003c/groupId\u003e\n\t\u003cartifactId\u003eform-binding\u003c/artifactId\u003e\n\t\u003cversion\u003eSEE THE RELEASES TAB FOR VERSION NUMBER\u003c/version\u003e\n\t\u003cscope\u003eruntime\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n#### Server\n\n* Accept forms easily without a ton of silly `@FormParam` annotations!\n\n```\n@ApplicationPath(\"/api/1.0\")\npublic class RestApplication extends Application {\n\t@Override\n\tpublic Set\u003cClass\u003c?\u003e\u003e getClasses() {\n\t\treturn new HashSet\u003cClass\u003c?\u003e\u003e(Arrays.asList(new Class\u003c?\u003e[] { RestResource.class, FormBindingMessageBodyReader.class }));\n\t}\n}\n```\n\n```\n@ApplicationScoped\n@Path(\"/testObject\")\n@Consumes({ MediaType.APPLICATION_FORM_URLENCODED })\npublic class RestResource {\n\t@POST\n\tpublic void testObjectForm(TestObject testObject) {\n\t\tSystem.out.println(testObject);\n\t}\n}\n```\n\n#### Client\n\n* Post an http form to a URL without creating an intermediary MultiValuedMap or JAX-RS `javax.ws.rs.core.Form` class:\n\n```\npublic void postTestObject(TestObject testObject) {\n\tClient client = ClientBuilder.newClient();\n\tclient.register(FormBindingMessageBodyWriter.class);\n\tclient.target(\"http://example.com\").path(\"testObject\").request().post(Entity.entity(testObject, MediaType.APPLICATION_FORM_URLENCODED));\n\tclient.close();\n}\n```\n\n* Read an `application/x-www-form-urlencoded` response back from a REST service!\n\n```\npublic TestObject getTestObject() {\n\tClient client = ClientBuilder.newClient();\n\tclient.register(FormBindingMessageBodyReader.class);\n\tTestObject testObject = client.target(\"http://example.com\").path(\"testObject\").request().accept(MediaType.APPLICATION_FORM_URLENCODED).get(TestObject.class);\n\tclient.close();\n\treturn testObject;\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexabrial%2Fform-binding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexabrial%2Fform-binding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexabrial%2Fform-binding/lists"}