{"id":18110389,"url":"https://github.com/v1ncnet/typed-ids","last_synced_at":"2026-05-01T13:31:47.136Z","repository":{"id":37804445,"uuid":"454443836","full_name":"V1ncNet/typed-ids","owner":"V1ncNet","description":"Collection of modular libraries for strong typed identifiers","archived":false,"fork":false,"pushed_at":"2023-12-25T11:18:49.000Z","size":496,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-12T13:22:17.853Z","etag":null,"topics":["identifier","jackson","spring-boot","spring-boot-autoconfigure","value-object"],"latest_commit_sha":null,"homepage":"https://v1ncnet.github.io/typed-ids/","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/V1ncNet.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":"2022-02-01T15:35:44.000Z","updated_at":"2022-02-03T13:29:38.000Z","dependencies_parsed_at":"2023-12-25T12:25:53.369Z","dependency_job_id":"9b3f52dc-5541-459a-afc9-9f0421484ccb","html_url":"https://github.com/V1ncNet/typed-ids","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/V1ncNet%2Ftyped-ids","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/V1ncNet%2Ftyped-ids/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/V1ncNet%2Ftyped-ids/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/V1ncNet%2Ftyped-ids/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/V1ncNet","download_url":"https://codeload.github.com/V1ncNet/typed-ids/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247451614,"owners_count":20940946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["identifier","jackson","spring-boot","spring-boot-autoconfigure","value-object"],"created_at":"2024-11-01T00:09:09.323Z","updated_at":"2026-05-01T13:31:47.082Z","avatar_url":"https://github.com/V1ncNet.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# :muscle: Typed Identifier Value Objects\n\nThis project is a collection of Value Objects that encourages the use of\nstrong typed identifiers. It also provides integrations for serialization\nlibraries such as Jackson.\n\n## Use Case\n\nImagine a service or repository, and you want to query an entity with two\ndistinct IDs. Let's say they're both UUIDs. There's no other possibility than to\ndifferentiate between the IDs via the name of the argument.\n\n```java\npublic Entity query(UUID fooId, UUID barId) {\n    ...\n}\n```\n\nThere are three options to minimize the risk to confound the arguments of\nthe method above.\n\n0. Be perfect and make no mistakes\n1. Verify the correctness with tests\n2. Change code design\n3. Use different argument types\n\nAlthough I'd recommend option 1 and 2, it's never a bad idea to be extra sure\nand avoid misuse from the start. Strong typing and extensive use of Value\nObjects helps to improve readability and encourages self documenting code.\n\n\n## Usage\n\nThe library can be used as is, but the real benefits only come when you\nderive the identifier for each domain entity. Let's assume you hava an entity\ncalled Person. Your code could read something like this.\n\n```java\npublic class Person {\n\n    private final Person.Id id;\n    private String name;\n\n    // constructor, getter and setter omitted for brevity\n\n    public static final class Id extends UuidIdentifier {\n\n        public Id(UUID value) {\n            super(value);\n        }\n    }\n}\n```\n\n\n## Modules\n\nNone of the modules below will ship transitive dependencies. Unless you are\nusing a Spring Boot Starter Parent, you want to make sure to include the\ndependencies yourself.\n\n### API\n\nThe API module contains the core code base. Other modules are built on top of\nthe API.  The usage is pretty self-explanatory. It contains the identifier,\nfactories and basic subtypes. The `Identifiable` interface is for convenience\nmay be implemented by any domain entities.\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.vinado.lib\u003c/groupId\u003e\n    \u003cartifactId\u003eidentifier-api\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Jackson\n\nThis module contains JSON deserializers for all generic base identifiers and a\ngeneric serializer that delegates to the ID value's serializer. Their purpose is\nto unwrap the value object into a plain JSON value. So the JSON tree stays clean\nand familiar to existing APIs (or at least to you and your OCDs).\n\nIf you want to derive from a basic identifier, you also need to implement a\ncustom deserializer. The following example shows the amount of work that is\nnecessary. Not much right?\n\n```java\n@JsonDeserialize(using = Id.Deserializer.class)\npublic final class Id extends UuidIdentifier {\n\n    public Id(UUID value) {\n        super(value);\n    }\n\n    private static final class Deserializer extends UuidIdentifierDeserializer\u003cId\u003e {\n\n        private Deserializer() {\n            super(Id::new);\n        }\n    }\n}\n```\n\n---\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.vinado.lib\u003c/groupId\u003e\n    \u003cartifactId\u003eidentifier-jackson\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.fasterxml.jackson.core\u003c/groupId\u003e\n    \u003cartifactId\u003ejackson-databind\u003c/artifactId\u003e\n    \u003cversion\u003e${jackson.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Spring\n\nThe Spring module contains generic identifier (reading) converters. They are\ncapable of converting any compatible value to the corresponding identifier\n**and subtypes**. This is especially useful for Spring Web applications and you\nwant to query resources by their identifier, like the following example shows.\n\n```java\n@GetMapping(\"/{id}\")\npublic ResponseEntity\u003cPerson\u003e retrieve(@PathVariable Person.Id id) {\n    ...\n}\n```\n\nThe identifier instantiation is performed via Java reflection. Therefor subtypes\nmust provide an accessible constructor that takes exactly on argument of the\ntype the identifier encapsulates.\n\n---\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.vinado.spring\u003c/groupId\u003e\n    \u003cartifactId\u003eidentifier-convert\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework\u003c/groupId\u003e\n    \u003cartifactId\u003espring-core\u003c/artifactId\u003e\n    \u003cversion\u003e${spring.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Spring Boot\n\nIn case you wish to integrate strong typed identifiers into your Spring Boot\napplication you may want to use the zero-conf Spring Boot Starter.\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ede.vinado.boot\u003c/groupId\u003e\n    \u003cartifactId\u003eidentifier-spring-boot-starter\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Licence\n\nApache License 2.0 - [Vinado](https://vinado.de) - Built with :heart: in Dresden\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fv1ncnet%2Ftyped-ids","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fv1ncnet%2Ftyped-ids","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fv1ncnet%2Ftyped-ids/lists"}