{"id":31530193,"url":"https://github.com/frictionlessdata/tableschema-swift","last_synced_at":"2025-10-04T01:19:17.231Z","repository":{"id":63910206,"uuid":"244607323","full_name":"frictionlessdata/tableschema-swift","owner":"frictionlessdata","description":"A Swift library for working with Table Schema.","archived":false,"fork":false,"pushed_at":"2022-12-19T06:58:05.000Z","size":34,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-09-25T21:47:52.738Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","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/frictionlessdata.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-03T10:30:33.000Z","updated_at":"2023-03-13T14:15:12.000Z","dependencies_parsed_at":"2022-11-29T07:14:22.954Z","dependency_job_id":null,"html_url":"https://github.com/frictionlessdata/tableschema-swift","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/frictionlessdata/tableschema-swift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frictionlessdata%2Ftableschema-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frictionlessdata%2Ftableschema-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frictionlessdata%2Ftableschema-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frictionlessdata%2Ftableschema-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frictionlessdata","download_url":"https://codeload.github.com/frictionlessdata/tableschema-swift/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frictionlessdata%2Ftableschema-swift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278252174,"owners_count":25956257,"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-03T02:00:06.070Z","response_time":53,"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":[],"created_at":"2025-10-04T01:19:06.697Z","updated_at":"2025-10-04T01:19:17.225Z","avatar_url":"https://github.com/frictionlessdata.png","language":"Swift","readme":"# tableschema-swift\n\n[![Build](https://github.com/frictionlessdata/tableschema-swift/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/frictionlessdata/tableschema-swift/actions/workflows/tests.yml)\n[![Coverage](https://coveralls.io/repos/github/frictionlessdata/tableschema-swift/badge.svg?branch=main)](https://coveralls.io/github/frictionlessdata/tableschema-swift?branch=main)\n[![Codebase](https://img.shields.io/badge/codebase-github-brightgreen)](https://github.com/frictionlessdata/tableschema-swift)\n[![Support](https://img.shields.io/badge/support-discord-brightgreen)](https://discordapp.com/invite/Sewv6av)\n\nThis is a Swift language implementation of [TableSchema](https://frictionlessdata.io/specs/table-schema/) for defining schemas to work with tabular data.\n\nA schema on tabular data defines types, imposes constraints, and creates foreign key relationships on fields as data values move from some physical representation to a logical one and vice versa. For instance, a stored CSV file (physical) can be loaded in-memory along with a corresponding schema descriptor to be transformed from string values to Swift Standard Library types like `Date` or `Int` (logical).\n\n## Requirements\n * Source compatibility with Swift 4.2\n * Target platforms\n    * Apple platforms, specifically iOS and macOS\n       * Full functionality in iOS \u003e= 10 and macOS \u003e= 10.12\n    * Linux, limited by features available in `swift-corelibs-foundation`\n * Apple's `Foundation` framework is the only dependency\n * Independent from any one particular physical representation\n\n## Implementation Status\nAlthough incomplete this library is being used in at least one shipping product over a subset of the available features. Field types that are unsupported will not be transformed resulting in potential data loss on those unsupported types. Please consult the following tables. There is a testing suite to keep what should be working in check. Contributions are welcome.\n\n### Feature Status\n| Feature                         | Status                            |\n|:--------------------------------|:----------------------------------|\n| Streaming and cast on iteration | Available                         |\n| Casting field types and formats | Partial                           |\n| [De]serialization               | Available in Tabular Data Package |\n| Schema inference                | Missing (Unlikely to implement)   |\n| Strict mode                     | Missing                           |\n| Constraint validation           | Missing                           |\n| Foreign key validation          | Missing                           |\n| Rich (RDF) Types                | Missing (Unlikely to implement)   |\n\n### Casting Field Types and Formats Status\n| Type      | Formats                    | Additional Properties   | Forward Status (Physical to Logical) | Reverse Status (Logical to Physical) |\n|:----------|:---------------------------|:------------------------|:-------------------------------------|:-------------------------------------|\n| string    | default, uri, binary, uuid | *N/A*                   | Available                            | Available                            |\n| string    | email                      | *N/A*                   | Unavailable                          | Unavailable                          |\n| number    | *N/A*                      | *Any*                   | Unavailable                          | Unavailable                          |\n| integer   | *N/A*                      | bareNumber = false      | Available*                           | Available                            |\n| integer   | *N/A*                      | bareNumber = true       | Available                            | Available                            |\n| boolean   | *N/A*                      | trueValues, falseValues | Available                            | Available                            |\n| object    | *N/A*                      | *N/A*                   | Available                            | Unavailable                          |\n| array     | *N/A*                      | *N/A*                   | Available                            | Available                            |\n| date      | *N/A*                      | default                 | Available*                           | Unavailable                          |\n| date      | *N/A*                      | any, pattern            | Unavailable                          | Unavailable                          |\n| time      | *N/A*                      | default                 | Available*                           | Unavailable                          |\n| time      | *N/A*                      | any, pattern            | Unavailable                          | Unavailable                          |\n| datetime  | *N/A*                      | default                 | Available*                           | Available*                           |\n| datetime  | *N/A*                      | any, pattern            | Unavailable                          | Unavailable                          |\n| year      | *N/A*                      | *N/A*                   | Available*                           | Unavailable                          |\n| yearmonth | *N/A*                      | *N/A*                   | Available*                           | Unavailable                          |\n| duration  | *N/A*                      | *N/A*                   | Available*                           | Unavailable                          |\n| geopoint  | default, array, object     | *N/A*                   | Available                            | Unavailable                          |\n| geojson   | default, topo              | *N/A*                   | Unavailable                          | Unavailable                          |\n| any       | *N/A*                      | *N/A*                   | Unavailable                          | Unavailable                          |\n\n\\* Only available on Apple products (namely iOS and macOS) due to an incomplete implementation in `swift-corelibs-foundation`\n\n## Integration into Your Project\nThis project is set up using [Swift Package Manager](https://swift.org/package-manager/). Ideally add it to your project's SPM dependencies or use Xcode's integrated Swift Package Manager. Alternatively, generate your own Xcode `.xcodeproj` to integrate with your build system using:\n\n```bash\nswift package generate-xcodeproj --xcconfig-overrides ./Configuration.xcconfig\n```\n\n## Example Usage\n\n### Cast on Iteration from a Data Source\nDeserializing of data (from, say, a CSV file) can be accomplished by setting up a `Table` with an iterator that provides row information using a `TableProvider` data source. This allows for the data source to stream data rather than necessarily loading everything in-memory. `Table` is agnostic from the specific data source but expects the data source to convert to `String` representations.\n\n```swift\nlet sourcePath = \"import.csv\"\nlet sourceDialect = DialectalCSV.Dialect()\n\nlet fields = [Field(\"name\", type: .string), Field(\"birthday\", type: .date)]\nlet schema = Schema(fields)\n\nguard let provider = MyTableProvider(atPath: sourcePath, dialect: sourceDialect) else {\n    fatalError(\"Oops\")\n}\nlet table = Table(provider: AnyTableProvider(provider), schema: schema)\nlet objects = table.map { $0 }\n```\n\nAnd defining `MyTableProvider` together with a CSV parsing library like `DialectalCSV`:\n\n```swift\nclass MyTableProvider: TableProvider {\n\n    private let handler: DialectalCSV.InputHandler\n    private let streamIterator: DialectalCSV.InputIterator\n\n    init?(atPath path: String, dialect: DialectalCSV.Dialect) {\n        guard let handler = DialectalCSV.InputHandler(atPath: path, dialect: dialect) else {\n            return nil\n        }\n        self.handler = handler\n        self.streamIterator = handler.makeIterator()\n    }\n\n    // MARK: - TableProvider\n\n    var header: Header? {\n        return self.streamIterator.header\n    }\n\n    // MARK: - Sequence\n\n    func makeIterator() -\u003e AnyIterator\u003c[String?]\u003e {\n        return AnyIterator {\n            return self.streamIterator.next()\n        }\n    }\n\n}\n```\n\n### Reverse Casting (Logical to Physical)\n\nCast the entire data set in-memory:\n\n```swift\nlet objects = [[Any?]]()\nlet rows = objects.map { schema.reverseCast(row: $0) }\n```\n\nOr streaming output using a CSV parsing library like `DialectalCSV`:\n\n```swift\nlet objects: [[Any?]] = [[\"River Tam\", Date(timeIntervalSince1970: 16725225600)],[\"Simon Tam\", nil]]\n\nlet destinationPath = \"export.csv\"\nvar destinationDialect = DialectalCSV.Dialect()\ndestinationDialect.nullSequence = \"null\"\n\nFileManager.default.createFile(atPath: destinationPath, contents: nil)\nguard let outputHandler = DialectalCSV.OutputHandler(atPath: destinationPath, dialect: destinationDialect) else {\n    fatalError(\"Oops\")\n}\n\nlet header = schema.fields.map { $0.name }\ntry? outputHandler.open(header: header)\n\nfor object in objects {\n    let row = schema.reverseCast(row: object).map { $0 }\n    try? outputHandler.append(records: [row])\n}\n\ntry? outputHandler.close()\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrictionlessdata%2Ftableschema-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrictionlessdata%2Ftableschema-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrictionlessdata%2Ftableschema-swift/lists"}