{"id":19446255,"url":"https://github.com/devskiller/friendly-id","last_synced_at":"2025-10-04T16:14:39.508Z","repository":{"id":25757683,"uuid":"105585951","full_name":"Devskiller/friendly-id","owner":"Devskiller","description":"Java Friendly Id for UUID","archived":false,"fork":false,"pushed_at":"2024-05-07T13:25:03.000Z","size":252,"stargazers_count":218,"open_issues_count":2,"forks_count":14,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-07-25T07:36:04.019Z","etag":null,"topics":["base62","jackson","spring-boot","unique-id","unique-identifier","url62","url64","uuid"],"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/Devskiller.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":"2017-10-02T21:16:07.000Z","updated_at":"2025-07-08T12:34:14.000Z","dependencies_parsed_at":"2024-12-22T12:12:13.870Z","dependency_job_id":"f72a845b-9ffe-4afc-83bd-c1e9f640bc3d","html_url":"https://github.com/Devskiller/friendly-id","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/Devskiller/friendly-id","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devskiller%2Ffriendly-id","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devskiller%2Ffriendly-id/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devskiller%2Ffriendly-id/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devskiller%2Ffriendly-id/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Devskiller","download_url":"https://codeload.github.com/Devskiller/friendly-id/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devskiller%2Ffriendly-id/sbom","scorecard":{"id":40084,"data":{"date":"2025-08-11","repo":{"name":"github.com/Devskiller/friendly-id","commit":"bc63e0a8f95981482771958a530e44000470d2bc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Code-Review","score":1,"reason":"Found 3/30 approved changesets -- score normalized to 1","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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/maven.yml:1","Info: no jobLevel write permissions found"],"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":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: .mvn/wrapper/maven-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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/Devskiller/friendly-id/maven.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/maven.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/Devskiller/friendly-id/maven.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"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":"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":"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: 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":-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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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 4 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"}},{"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"}}]},"last_synced_at":"2025-08-14T21:17:37.512Z","repository_id":25757683,"created_at":"2025-08-14T21:17:37.512Z","updated_at":"2025-08-14T21:17:37.512Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278337312,"owners_count":25970492,"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","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["base62","jackson","spring-boot","unique-id","unique-identifier","url62","url64","uuid"],"created_at":"2024-11-10T16:13:20.818Z","updated_at":"2025-10-04T16:14:39.467Z","avatar_url":"https://github.com/Devskiller.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/Devskiller/friendly-id.svg?branch=master)](https://travis-ci.org/Devskiller/friendly-id)  [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.devskiller.friendly-id/friendly-id/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.devskiller.friendly-id/friendly-id)  [![Coverage Status](https://coveralls.io/repos/github/Devskiller/friendly-id/badge.svg?branch=master)](https://coveralls.io/github/Devskiller/friendly-id?branch=master) \n\nFriendlyID (Java, [Swift](https://github.com/kdubb/SwiftFriendlyId), [Rust](https://github.com/mariuszs/friendly_id), [Go](https://github.com/mariuszs/friendlyid-go))\n==\n\n\nWhat is the FriendlyID library?\n--\nThe FriendlyID library converts a given UUID (with 36 characters) to a URL-friendly ID (a \"FriendlyID\") which is based on Base62 (with a maximum of 22 characters), as in the example below:\n\n\n    UUID                                        Friendly ID\n    \n    c3587ec5-0976-497f-8374-61e0c2ea3da5   -\u003e   5wbwf6yUxVBcr48AMbz9cb\n    |                                           |                              \n    36 characters                               22 characters or less\n\nIn addition, this library allows to:\n \n\n* convert from a FriendlyID back to the original UUID; and\n* create a new, random FriendlyID\n\nWhy use a FriendlyID?\n--\nUniversal Unique IDs (UUIDs) provide a non-sequential and unique identifier that can be generated separately from the source database. As a result, it is not possible to guess either the previous or next identifier. That's great, but, to achieve this level of security, a UUID is long (128 bits long) and looks ugly (36 alphanumeric characters including four hyphens which are added to make it easier to read the UUID), as in this example: `123e4567-e89b-12d3-a456-426655440000`.\n\nSuch a format is:\n\n* difficult to read (especially if it is part of a URL)\n* difficult to remember\n* cannot be copied with just two mouse-clicks (you have to select manually the start and end positions)\n* can easily become broken across lines when it is copied, pasted, edited, or sent.\n\n\nOur FriendlyID Java library solves these problems by converting a given UUID using Base62 with alphanumeric characters in the range [0-9A-Za-z] into a FriendlyId which consists of a maximum of 22 characters (but in fact often contains fewer characters).\n\nSupported languages\n--\n\nCurently FriendlyId supports Java (this project) and\n * [Swift](https://github.com/kdubb/SwiftFriendlyId) language (thanks to [Kevin Wooten](https://github.com/kdubb))\n * [Rust](https://github.com/mariuszs/friendly_id) [![Version](https://img.shields.io/crates/v/friendly_id.svg?style=social\u0026logo=appveyor)](https://crates.io/crates/friendly_id)\n * [Go](https://github.com/mariuszs/friendlyid-go) \n\nTools\n--\n\nThere are available CLI converters for many platforms.\n\n* https://github.com/mariuszs/rust-friendlyid (also available in RPM and DEB format)\n* https://github.com/kdubb/SwiftFriendlyId#command-line\n\n## Use cases\n\n### Basic (returning a user in a database)\n\n\nLet us assume that a method in the controller for returning users requires the relevant UUID in order to find a given user in a database, as in this example:\n\n```java\n@GetMapping(\"/users/{userId}\") \npublic User getUser(@PathVariable UUID userId) {\n        [implementation deleted]\n}\n```\n\nWithout using the Friendly ID library, you could access a given user as follows:\n\n```bash\ncurl http://localhost:8080/users/c3587ec5-0976-497f-8374-61e0c2ea3da5\n```\n\n\nAfter adding the FriendlyID library, the controller method itself does not change, but you would be able to access a given user using the relevant FriendlyID as follows: \n\n```bash\ncurl http://localhost:8080/users/5wbwf6yUxVBcr48AMbz9cb\n```\n\n\n\nIn addition, if a given document returned by such a method contains objects of type UUID, those IDs will also be shortened into FriendlyID format.\n\n\n### Advanced (Optimizing testing)\n\n \n The FriendlyID library makes it possible to define for UUIDs values which are easy to read. By using names instead of hard-to-remember UUIDs, you can write much simpler tests for your code, for example:\n \n```java\n@Test \npublic void shouldGetUser() { \n    mockMvc.perform(get(\"/users/{userId}\", \"John\")) \n        .andExpect(status().isOk()) \n        .andExpect(content().contentType(\"application/json\")) \n        .andExpect(jsonPath(\"$.uuid\", is(\"John\"))); \n} \n```\n\nIn the above example, the variable \"John\" is decoded by the library to the correct UUID, in this case, `00000000-0000-0000-0000-000000a69efb`. In this way, you can give a variable in a test class a truly meaningful value and, as a result, an assertion which refers to that variable becomes exceptionally easy to understand in your test program.\n\n\nFriendlyID library \n--\n\nDependencies\n---\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.devskiller.friendly-id\u003c/groupId\u003e\n    \u003cartifactId\u003efriendly-id\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nUsage\n---\n\n```java\nFriendlyId.createFriendlyId();\n```\n\nThis creates a new, random FriendlyID, for example: `5wbwf6yUxVBcr48AMbz9cb`\n\n```java\nFriendlyId.toFriendlyId(UUID.fromString(\"c3587ec5-0976-497f-8374-61e0c2ea3da5\"));\n```\n\nThis converts a UUID in the form of a string to a FriendlyID, for example: `5wbwf6yUxVBcr48AMbz9cb`\n\n\n ```java\nFriendlyId.toUuid(\"5wbwf6yUxVBcr48AMbz9cb\");\n```\n\nThis converts a FriendlyID to its UUID, for example: `c3587ec5-0976-497f-8374-61e0c2ea3da5`\n\n\nNotes\n--\n\t\n* As every *UUID* is a 128-bit number, a *FriendlyID* can also store only a 128-bit number.\n* If a FriendlyID has any leading zeros, those leading zeros are ignored - for example, `00cafe` is treated as `cafe`.\n\n\n## Integrations\n\n\n- [Spring Boot integration](#Spring-Boot-integration)\n- [Jackson integration ](#Jackson-integration)\n\n### Spring Boot integration\n\nThe FriendlyID library includes a Spring configuration to make it easy to add shorter IDs to an application. With a typical application based on Spring Boot, for your controllers to be able to use FriendlyIDs when communicating with the outside world, just add one new starter dependency as follows:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.devskiller.friendly-id\u003c/groupId\u003e\n    \u003cartifactId\u003efriendly-id-spring-boot-starter\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n    \nLet us assume that you'll use this sample application:\n\n```java\n@SpringBootApplication\n@RestController\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication.run(Application.class, args);\n    }\n\n    @GetMapping(\"/bars/{bar}\")\n    public Bar getBar(@PathVariable UUID bar) {\n        return new Bar(UUID.randomUUID());\n    }\n\n    @Value\n    class Bar {\n        private final UUID id;\n    }\n}  \n```   \n    \nThis command: `curl http://localhost:8080/bars/5fD1KwsxRcGhBqWNju0jzt` \n\nwill result in the following output: \n```json\n{\"id\":\"52OMXhWiAqUWwII0c97Svl\"}\n```    \n\nIn this case, `Bar` is a POJO class which is converted by Spring MVC to a JSON document. This `Bar` object has one field of type UUID, and this field is output to the JSON document as a FriendlyID instead of a UUID. Although the application uses the relevant UUID internally, from an external point of view, only the FriendlyID is visible.    \n\n### Jackson integration    \n\n\nFirst, add the following Jackson module dependency:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.devskiller.friendly-id\u003c/groupId\u003e\n    \u003cartifactId\u003efriendly-id-jackson-datatype\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\nThen register the `FriendlyIdModule` module as follows:\n\n```java\nObjectMapper mapper = new ObjectMapper()\n   .registerModule(new FriendlyIdModule());\n```\n\nContributing\n----------\n\nThinking of helping us out? We invite you to take a look at:\n\n- Source Code: [github.com/Devskiller/friendly-id/](https://github.com/Devskiller/friendly-id)\n- Issue Tracker: [github.com/Devskiller/friendly-id/issues](https://github.com/Devskiller/friendly-id/issues)\n\n\nLicense\n-------\n\nThe project is licensed under the Apache 2.0 license.\nFor further details, please see the [License](/LICENSE/) page. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevskiller%2Ffriendly-id","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevskiller%2Ffriendly-id","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevskiller%2Ffriendly-id/lists"}