{"id":31765122,"url":"https://github.com/piashcse/zodkmp","last_synced_at":"2026-05-05T18:39:53.936Z","repository":{"id":317989210,"uuid":"1066506815","full_name":"piashcse/ZodKmp","owner":"piashcse","description":"ZodKmp is a Kotlin Multiplatform implementation of the popular Zod TypeScript validation library. It provides a declarative, type-safe way to validate data in your Kotlin Multiplatform projects.","archived":false,"fork":false,"pushed_at":"2025-10-04T10:21:58.000Z","size":367,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-04T11:30:48.584Z","etag":null,"topics":["android","cmp","desktop","ios","kmp","kotlin","kotlin-multiplatform","kotlin-validators","validation","wasmjs","zod","zod-kmp","zod-validation","zodkmp"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piashcse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-29T15:20:56.000Z","updated_at":"2025-10-04T10:24:22.000Z","dependencies_parsed_at":"2025-10-09T22:31:08.530Z","dependency_job_id":null,"html_url":"https://github.com/piashcse/ZodKmp","commit_stats":null,"previous_names":["piashcse/zodkmp"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/piashcse/ZodKmp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piashcse%2FZodKmp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piashcse%2FZodKmp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piashcse%2FZodKmp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piashcse%2FZodKmp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piashcse","download_url":"https://codeload.github.com/piashcse/ZodKmp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piashcse%2FZodKmp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002382,"owners_count":26083356,"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-09T02:00:07.460Z","response_time":59,"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":["android","cmp","desktop","ios","kmp","kotlin","kotlin-multiplatform","kotlin-validators","validation","wasmjs","zod","zod-kmp","zod-validation","zodkmp"],"created_at":"2025-10-10T00:13:26.799Z","updated_at":"2026-05-05T18:39:53.928Z","avatar_url":"https://github.com/piashcse.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ZodKmp: Kotlin Multiplatform Validation\n\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.piashcse/zodkmp.svg)](https://search.maven.org/artifact/io.github.piashcse/zodkmp)\n[![Kotlin Version](https://img.shields.io/badge/kotlin-2.2.20-blue.svg?logo=kotlin)](http://kotlinlang.org)\n![badge-Android](https://img.shields.io/badge/Platform-Android-brightgreen)\n![badge-iOS](https://img.shields.io/badge/Platform-iOS-lightgray)\n![badge-desktop](http://img.shields.io/badge/Platform-Desktop-4D76CD.svg?style=flat)\n![badge-web](https://img.shields.io/badge/Platform-Web-blueviolet.svg?style=flat)\n[![License](https://img.shields.io/github/license/colinhacks/zod)](LICENSE)\n\u003ca href=\"https://github.com/piashcse\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/static/v1?label=GitHub\u0026message=piashcse\u0026color=C51162\"/\u003e\u003c/a\u003e\n\nZodKmp is a Kotlin Multiplatform implementation of the popular [Zod](https://zod.dev/) TypeScript validation library. It provides a declarative, type-safe way to validate data in your Kotlin Multiplatform projects. For detail [documentation ](https://piashcse.github.io/ZodKmp/).\n\n\n## Platform Support\n\nZodKmp supports the following platforms:\n\n- Android (JVM)\n- iOS (Native)\n- JVM\n- JS (JavaScript)\n- Native (Linux, Windows, macOS)\n\n\n## Installation\n\n### Gradle\n\nAdd the following to your `build.gradle.kts`:\n\n```kotlin\nkotlin {\n    sourceSets {\n        val commonMain by getting {\n            dependencies {\n                implementation(\"io.github.piashcse:zodkmp:1.2.0\")\n            }\n        }\n    }\n}\n```\n\n### Version Catalog (libs.versions.toml)\n\n```toml\n[versions]\nzodkmp = \"1.2.0\"\n\n[libraries]\nzodkmp = { module = \"io.github.piashcse:zodkmp\", version.ref = \"zodkmp\" }\n```\n\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n- [API Reference](#api-reference)\n  - [Primitives](#primitives)\n  - [Literals](#literals)\n  - [Strings](#strings)\n  - [Numbers](#numbers)\n  - [Booleans](#booleans)\n  - [Dates](#dates)\n  - [Arrays](#arrays)\n  - [Objects](#objects)\n  - [Unions](#unions)\n  - [Enums](#enums)\n  - [Tuples](#tuples)\n  - [Records](#records)\n  - [Intersections](#intersections)\n  - [Nullables](#nullables)\n  - [Optionals](#optionals)\n  - [Transformations](#transformations)\n  - [Refinements](#refinements)\n  - [Defaults](#defaults)\n- [Advanced Usage](#advanced-usage)\n- [Platform Support](#platform-support)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n- ✅ **Declarative Schema Definition** - Define validation rules upfront\n- ✅ **Type Inference** - Automatic type inference from schemas\n- ✅ **Immutable Architecture** - Immutable schemas that return new instances\n- ✅ **Kotlin Multiplatform** - Works on Android, iOS, and other Kotlin targets\n- ✅ **Comprehensive API** - Supports all major Zod validation features\n- ✅ **Extensible** - Easy to extend with custom validations\n- ✅ **Zero Dependencies** - Lightweight with minimal footprint\n- ✅ **Excellent Error Messages** - Detailed, customizable error reporting\n- \n## Getting Started\n\nZodKmp allows you to define validation schemas and use them to validate data:\n\n```kotlin\nimport com.piashcse.zodkmp.Zod\n\n// Define a schema\nval userSchema = Zod.objectSchema\u003cUser\u003e({\n    string(\"name\", Zod.string().min(2))\n    string(\"email\", Zod.string().email())\n    number(\"age\", Zod.number().min(0).max(120))\n}) { map -\u003e\n    User(\n        name = map[\"name\"] as String,\n        email = map[\"email\"] as String,\n        age = (map[\"age\"] as Number).toDouble()\n    )\n}\n\n// Use the schema\nval userData = mapOf(\n    \"name\" to \"John Doe\",\n    \"email\" to \"john@example.com\",\n    \"age\" to 30.0\n)\n\nval result = userSchema.safeParse(userData)\nwhen (result) {\n    is ZodResult.Success -\u003e println(\"Valid user: ${result.data}\")\n    is ZodResult.Failure -\u003e println(\"Validation errors: ${result.error.errors}\")\n}\n```\n\n## API Reference\n\n### Primitives\n\n#### String\nValidate string values with various constraints:\n\n```kotlin\nval stringSchema = Zod.string()\n\n// With constraints\nval constrainedString = Zod.string()\n    .min(5, \"String must be at least 5 characters\")\n    .max(100, \"String must be at most 100 characters\")\n    .length(10, \"String must be exactly 10 characters\")\n    .email(\"Must be a valid email address\")\n    .url(\"Must be a valid URL\")\n    .regex(Regex(\"^[A-Za-z]+$\"), \"Must contain only letters\")\n    .startsWith(\"Hello\", \"Must start with 'Hello'\")\n    .endsWith(\"World\", \"Must end with 'World'\")\n    .includes(\"test\", \"Must contain 'test'\")\n    .toLowerCase()\n    .toUpperCase()\n    .trim()\n```\n\n#### Number\nValidate numeric values:\n\n```kotlin\nval numberSchema = Zod.number()\n\n// With constraints\nval constrainedNumber = Zod.number()\n    .gt(0, \"Must be greater than 0\")\n    .gte(5, \"Must be greater than or equal to 5\")\n    .lt(100, \"Must be less than 100\")\n    .lte(50, \"Must be less than or equal to 50\")\n    .min(10, \"Must be at least 10\")\n    .max(90, \"Must be at most 90\")\n    .int(\"Must be an integer\")\n    .positive(\"Must be positive\")\n    .negative(\"Must be negative\")\n    .nonPositive(\"Must be non-positive\")\n    .nonNegative(\"Must be non-negative\")\n    .multipleOf(5, \"Must be a multiple of 5\")\n```\n\n#### Boolean\nValidate boolean values:\n\n```kotlin\nval booleanSchema = Zod.boolean()\n```\n\n#### Date\nValidate date values:\n\n```kotlin\nval dateSchema = Zod.date()\n\n// With constraints\nval constrainedDate = Zod.date()\n    .min(LocalDateTime(2020, 1, 1, 0, 0), \"Date must be after 2020\")\n    .max(LocalDateTime(2030, 12, 31, 23, 59), \"Date must be before 2030\")\n```\n\n#### Null \u0026 Undefined\nValidate null and undefined values:\n\n```kotlin\nval nullSchema = Zod.null()\nval undefinedSchema = Zod.undefined()\n```\n\n### Literals\n\nValidate exact literal values:\n\n```kotlin\nval literalSchema = Zod.literal(\"admin\")\nval numberLiteral = Zod.literal(42)\nval booleanLiteral = Zod.literal(true)\n```\n\n### Arrays\n\nValidate array values with constraints:\n\n```kotlin\nval stringArray = Zod.array(Zod.string())\n\n// With constraints\nval constrainedArray = Zod.array(Zod.string())\n    .min(2, \"Array must have at least 2 elements\")\n    .max(10, \"Array must have at most 10 elements\")\n    .length(5, \"Array must have exactly 5 elements\")\n    .nonempty(\"Array must not be empty\")\n```\n\n### Objects\n\nValidate complex objects:\n\n```kotlin\nval userSchema = Zod.objectSchema\u003cUser\u003e({\n    string(\"name\", Zod.string().min(2))\n    string(\"email\", Zod.string().email())\n    number(\"age\", Zod.number().min(0).max(120))\n    field(\"isActive\", Zod.boolean().default(true))\n}) { map -\u003e\n    User(\n        name = map[\"name\"] as String,\n        email = map[\"email\"] as String,\n        age = (map[\"age\"] as Number).toDouble(),\n        isActive = map[\"isActive\"] as? Boolean ?: true\n    )\n}\n\n// Strict objects (reject unknown keys)\nval strictUserSchema = Zod.objectSchema\u003cUser\u003e({\n    string(\"name\", Zod.string().min(2))\n    string(\"email\", Zod.string().email())\n}) { map -\u003e\n    User(\n        name = map[\"name\"] as String,\n        email = map[\"email\"] as String\n    )\n}.strict()\n```\n\n### Enums\n\nValidate enum values:\n\n```kotlin\n// String enums\nval roleSchema = Zod.enum(\"admin\", \"user\", \"guest\")\n\n// Using collections\nval roles = listOf(\"admin\", \"user\", \"guest\")\nval roleSchema = Zod.enum(roles)\n```\n\n### Unions\n\nValidate values that match any of multiple schemas:\n\n```kotlin\nval stringOrNumber = Zod.union(Zod.string(), Zod.number())\nval complexUnion = Zod.union(\n    Zod.string(),\n    Zod.number(),\n    Zod.objectSchema\u003cPoint\u003e({\n        number(\"x\", Zod.number())\n        number(\"y\", Zod.number())\n    }) { map -\u003e\n        Point(\n            x = (map[\"x\"] as Number).toDouble(),\n            y = (map[\"y\"] as Number).toDouble()\n        )\n    }\n)\n```\n\n### Tuples\n\nValidate fixed-length arrays with specific types for each position:\n\n```kotlin\nval coordinates = Zod.tuple(listOf(Zod.number(), Zod.number()))\n\n// Usage\nval result = coordinates.safeParse(listOf(10.0, 20.0))\n```\n\n### Records\n\nValidate objects with string keys and uniform value types:\n\n```kotlin\nval stringRecord = Zod.record(Zod.string())\nval numberRecord = Zod.record(Zod.number())\n\n// Usage\nval userData = mapOf(\"name\" to \"John\", \"city\" to \"NYC\")\nval result = stringRecord.safeParse(userData)\n```\n\n### Intersections\n\nValidate values that must satisfy multiple schemas:\n\n```kotlin\nval personSchema = Zod.objectSchema\u003cPerson\u003e({\n    string(\"name\", Zod.string())\n}) { map -\u003e\n    Person(name = map[\"name\"] as String)\n}\n\nval employeeSchema = Zod.objectSchema\u003cEmployee\u003e({\n    string(\"employeeId\", Zod.string())\n}) { map -\u003e\n    Employee(employeeId = map[\"employeeId\"] as String)\n}\n\nval personEmployeeSchema = Zod.intersection(personSchema, employeeSchema)\n```\n\n### Nullables\n\nMark schemas as accepting null values:\n\n```kotlin\nval nullableString = Zod.string().nullable()\n\n// Usage\nval result1 = nullableString.safeParse(\"hello\") // Success\nval result2 = nullableString.safeParse(null)   // Success\nval result3 = nullableString.safeParse(42)       // Failure\n```\n\n### Optionals\n\nMark schemas as accepting undefined values:\n\n```kotlin\nval optionalString = Zod.string().optional()\n\n// Usage\nval result1 = optionalString.safeParse(\"hello\") // Success\nval result2 = optionalString.safeParse(null)     // Success (undefined)\n```\n\n### Transformations\n\nTransform values during validation:\n\n```kotlin\nval uppercaseString = Zod.string().transform { it.uppercase() }\nval toString = Zod.number().transform { it.toInt().toString() }\n\n// Usage\nval result = toString.safeParse(42.5) // Success with \"42\"\n```\n\n### Refinements\n\nAdd custom validation rules:\n\n```kotlin\nval evenNumber = Zod.number().refine({ it.toInt() % 2 == 0 }) { \"Number must be even\" }\nval strongPassword = Zod.string().refine({ it.length \u003e= 8 \u0026\u0026 it.any { char -\u003e char.isDigit() } }) { \"Password must be at least 8 characters with numbers\" }\n```\n\n### Defaults\n\nProvide default values for schemas:\n\n```kotlin\nval stringWithDefault = Zod.string().default(\"unknown\")\nval numberWithDefault = Zod.number().default { 0.0 }\n\n// Usage\nval result1 = stringWithDefault.safeParse(null)     // Success with \"unknown\"\nval result2 = stringWithDefault.safeParse(\"hello\")  // Success with \"hello\"\n```\n\n## Advanced Usage\n\n### Nested Object Validation\n\n```kotlin\nval addressSchema = Zod.objectSchema\u003cAddress\u003e({\n    string(\"street\", Zod.string().min(5))\n    string(\"city\", Zod.string().min(2))\n    string(\"zipCode\", Zod.string().regex(Regex(\"\\\\d{5}\"))\n}) { map -\u003e\n    Address(\n        street = map[\"street\"] as String,\n        city = map[\"city\"] as String,\n        zipCode = map[\"zipCode\"] as String\n    )\n}\n\nval userWithAddressSchema = Zod.objectSchema\u003cUserWithAddress\u003e({\n    string(\"name\", Zod.string().min(2))\n    field(\"address\", addressSchema)\n}) { map -\u003e\n    UserWithAddress(\n        name = map[\"name\"] as String,\n        address = map[\"address\"] as Address\n    )\n}\n```\n\n### Conditional Validation\n\n```kotlin\n// Custom validation based on other fields\nval conditionalSchema = Zod.objectSchema\u003cConditional\u003e({\n    string(\"type\", Zod.enum(\"email\", \"phone\"))\n    string(\"value\", Zod.string())\n}) { map -\u003e\n    Conditional(\n        type = map[\"type\"] as String,\n        value = map[\"value\"] as String\n    )\n}.refine({ obj -\u003e\n    when (obj.type) {\n        \"email\" -\u003e obj.value.contains(\"@\")\n        \"phone\" -\u003e obj.value.all { it.isDigit() || it == '-' }\n        else -\u003e true\n    }\n}) { \"Value must match the selected type\" }\n```\n\n### Error Handling\n\nZodKmp provides detailed error information:\n\n```kotlin\nval userSchema = Zod.objectSchema\u003cUser\u003e({\n    string(\"name\", Zod.string().min(2))\n    string(\"email\", Zod.string().email())\n}) { map -\u003e\n    User(\n        name = map[\"name\"] as String,\n        email = map[\"email\"] as String\n    )\n}\n\nval result = userSchema.safeParse(mapOf(\"name\" to \"A\", \"email\" to \"invalid-email\"))\n\nwhen (result) {\n    is ZodResult.Success -\u003e {\n        println(\"Valid data: ${result.data}\")\n    }\n    is ZodResult.Failure -\u003e {\n        result.error.errors.forEach { error -\u003e\n            println(\"Validation error: $error\")\n        }\n    }\n}\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## 👨 Developed By\n\n\u003ca href=\"https://twitter.com/piashcse\" target=\"_blank\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/piashcse\" width=\"90\" align=\"left\"\u003e\n\u003c/a\u003e\n\n**Mehedi Hassan Piash**\n\n[![Twitter](https://img.shields.io/badge/-Twitter-1DA1F2?logo=x\u0026logoColor=white\u0026style=for-the-badge)](https://twitter.com/piashcse)\n[![Medium](https://img.shields.io/badge/-Medium-00AB6C?logo=medium\u0026logoColor=white\u0026style=for-the-badge)](https://medium.com/@piashcse)\n[![Linkedin](https://img.shields.io/badge/-LinkedIn-0077B5?logo=linkedin\u0026logoColor=white\u0026style=for-the-badge)](https://www.linkedin.com/in/piashcse/)\n[![Web](https://img.shields.io/badge/-Web-0073E6?logo=appveyor\u0026logoColor=white\u0026style=for-the-badge)](https://piashcse.github.io/)\n[![Blog](https://img.shields.io/badge/-Blog-0077B5?logo=readme\u0026logoColor=white\u0026style=for-the-badge)](https://piashcse.blogspot.com)\n\n## License\n\n```\nMIT License\n\nCopyright (c) 2025 Mehedi Hassan Piash\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiashcse%2Fzodkmp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiashcse%2Fzodkmp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiashcse%2Fzodkmp/lists"}