{"id":32166567,"url":"https://github.com/primait/csv_schema","last_synced_at":"2026-02-20T00:31:53.130Z","repository":{"id":45306942,"uuid":"165835873","full_name":"primait/csv_schema","owner":"primait","description":"Csv schema is a library helping you to build Ecto.Schema-like modules having a csv file as source","archived":false,"fork":false,"pushed_at":"2026-02-03T03:14:16.000Z","size":635,"stargazers_count":28,"open_issues_count":2,"forks_count":1,"subscribers_count":45,"default_branch":"master","last_synced_at":"2026-02-12T12:55:54.144Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/csv_schema/Csv.Schema.html","language":"Elixir","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/primait.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":".github/CODEOWNERS","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":"2019-01-15T11:01:50.000Z","updated_at":"2026-01-05T11:53:49.000Z","dependencies_parsed_at":"2023-12-01T12:15:02.188Z","dependency_job_id":"b0660e92-6ae8-45b7-9825-ed7c911b3c33","html_url":"https://github.com/primait/csv_schema","commit_stats":{"total_commits":44,"total_committers":3,"mean_commits":"14.666666666666666","dds":"0.045454545454545414","last_synced_commit":"6c01ff12b40c8b61540ddd2573474f0063b7b2dc"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/primait/csv_schema","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primait%2Fcsv_schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primait%2Fcsv_schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primait%2Fcsv_schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primait%2Fcsv_schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/primait","download_url":"https://codeload.github.com/primait/csv_schema/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primait%2Fcsv_schema/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":[],"created_at":"2025-10-21T15:07:06.415Z","updated_at":"2026-02-20T00:31:53.124Z","avatar_url":"https://github.com/primait.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Csv Schema\n\n[![Build Status](https://travis-ci.org/primait/csv_schema.svg?branch=master)](https://travis-ci.org/primait/csv_schema)\n[![Module Version](https://img.shields.io/hexpm/v/csv_schema.svg)](https://hex.pm/packages/csv_schema)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/csv_schema/)\n[![Total Download](https://img.shields.io/hexpm/dt/csv_schema.svg)](https://hex.pm/packages/csv_schema)\n[![License](https://img.shields.io/hexpm/l/csv_schema.svg)](https://github.com/primait/csv_schema/blob/master/LICENSE)\n[![Last Updated](https://img.shields.io/github/last-commit/primait/csv_schema.svg)](https://github.com/primait/csv_schema/commits/master)\n\n\n\nCsv schema is a library helping you to build Ecto.Schema-like modules having a csv file as source.\n\nThe idea behind this library is give the possibility to create, at compile-time, a self-contained module exposing functions to retrieve data starting from a CSV.\n\n## Installation\n\nThe package can be installed by adding `:csv_schema` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:csv_schema, \"~\u003e 0.2.8\"}\n  ]\nend\n```\n\n## Usage\n\nSupposing you have a CSV file looking like this:\n\n  id | first_name | last_name  | email                         | gender | ip_address      | date_of_birth |\n:----|:-----------|:-----------|:------------------------------|:-------|:----------------|:--------------|\n1    | Ivory      | Overstreet | ioverstreet0@businessweek.com | Female | 30.138.91.62    | 10/22/2018    |\n2    | Ulick      | Vasnev     | uvasnev1@vkontakte.ru         | Male   | 35.15.164.70    | 01/19/2018    |\n3    | Chloe      | Freemantle | cfreemantle2@parallels.com    | Female | 133.133.113.255 | 08/13/2018    |\n...  | ...        | ...        | ...                           | ...    | ...             | ...           |\n\n\nIt is possible to create an Ecto.Schema-like repository using `Csv.Schema` macro:\n\n```elixir\ndefmodule Person do\n  use Csv.Schema\n  alias Csv.Schema.Parser\n\n  schema path: \"path/to/person.csv\" do\n    field :id, \"id\"\n    field :first_name, \"first_name\", filter_by: true\n    field :last_name, \"last_name\", sort: :asc\n    field :identifier, [\"first_name\", \"last_name\"], key: true, join: \" \"\n    field :email, \"email\", unique: true\n    field :gender, \"gender\", filter_by: true, sort: :desc\n    field :ip_address, \"ip_address\"\n    field :date_of_birth, \"date_of_birth\", parser: \u0026Parser.date!(\u00261, \"{0M}/{0D}/{0YYYY}\")\n  end\nend\n```\n\nIt is possible to define the schema with `string: ` param in order to directly use a string to generate content\n```elixir\n@data \"\"\"\nid,first_name,last_name,email,gender,ip_address,date_of_birth\n1,Ivory,Overstreet,ioverstreet0@businessweek.com,Female,30.138.91.62,10/22/2018\n2,Ulick,Vasnev,uvasnev1@vkontakte.ru,Male,35.15.164.70,01/19/2018\n3,Chloe,Freemantle,cfreemantle2@parallels.com,Female,133.133.113.255,08/13/2018\n\"\"\"\n\nschema data: @data do\n...\nend\n```\n\nNote that it's not a requirement to map all fields, but every field mapped must\nhave a column in csv file.\nFor example the following field configuration will result in a compilation error:\n\n```elixir\nfield :id, \"non_existing_id\", ...\n```\n\nSchema could be configured using a custom separator (default is ?,)\n```elixir\nuse Csv.Schema, separator: ?,\n```\n\nMoreover it's possible to configure if csv file has or has not an header. Depending on header param value field config changes:\n```elixir\n# Default header value is `true`\nuse Csv.Schema\n# Csv with header\nschema path: \"path/to/person.csv\" do\n  field :id, \"id\", key: true\n  ...\nend\n\n# Csv without header. Note that field 1 is binded with the first csv column.\nuse Csv.Schema, header: false\n# Index goes from 1 to N\nschema path: \"path/to/person.csv\" do\n  field :id, 1, key: true\n  ...\nend\n```\n\nNow Person module is a struct, defined like this:\n\n```elixir\ndefmodule Person do\n  defstruct id: nil,\n            first_name: nil,\n            last_name: nil,\n            email: nil,\n            gender: nil,\n            ip_address: nil,\n            date_of_birth: nil\nend\n```\n\nThis macro creates for you inside Person module those functions:\n\n```elixir\ndef by_id(integer_key), do: ...\n\ndef filter_by_first_name(string_value), do: ...\n\ndef by_email(string_value), do: ...\n\ndef filter_by_gender(string_value), do: ...\n\ndef get_all, do: ...\n```\n\nWhere:\n- `by_id` returns a `%Person{}` or `nil` if key is not mapped in csv\n- `filter_by_first_name` returns a `[%Person{}, %Person{}, ...]` or `[]` if input predicate does not match any person\n- `by_email` returns a `%Person{}` or `nil` if no person have provided email in csv\n- `filter_by_gender` returns a `[%Person{}, %Person{}, ...]` or `[]` if input predicate does not match any person gender\n- `get_all` return all csv rows as a Stream\n\n## Field configuration\n\nEvery field should be formed like this:\n\n```\nfield {struct_field}, {csv_header}, {opts}\n```\n\nwhere:\n- `{struct_field}` will be the struct field name. Could be configured as `string` or as `atom`\n- `{csv_header}` is the csv column name from where get values. Must be configured using string only\n- `{opts}` is a keyword list containing special configurations\n\nopts:\n- `:key` : boolean. At most one key could be set. If set to true creates the `by_{name}` function for you.\n- `:unique` : boolean. If set to true creates the `by_{name}` function for you. All csv values must be unique or an exception is raised\n- `:filter_by` : boolean. If set to true creates the `filter_by_{name}` function\n- `:parser` : function. An arity 1 function used to map values from string to a custom type\n- `:sort` : `:asc` or `:desc`. It sorts according to Erlang's term ordering with `nil` exception (`number \u003c atom \u003c reference \u003c fun \u003c port \u003c pid \u003c tuple \u003c list \u003c bit-string \u003c nil`)\n- `:join` : string. If present it joins the given fields into a binary using the separator\n\n\nNote that every configuration is optional\n\n## Keep in mind\n\nCompilation time increase in an exponential manner if csv contains lots of lines and you\nconfigure multiple fields candidate for method creation (flags `key`, `unique` and/or `filter_by` set to true).\n\nBecause \"without data you're just another person with an opinion\" here some data:\n\n### Compilation time\n\n| csv rows |   key | unique | filter_by |  compile time |\n| -------: | ----: | -----: | --------: | ------------: |\n|    1_000 | false |      0 |         0 |    301_727 µs |\n|    1_000 | false |      2 |         0 |    352_522 µs |\n|    1_000 | false |      0 |         4 |    318_225 µs |\n|    1_000 |  true |      0 |         0 |    334_240 µs |\n|    1_000 |  true |      1 |         1 |    348_697 µs |\n|    1_000 |  true |      2 |         0 |    406_367 µs |\n|    1_000 |  true |      0 |         4 |    385_850 µs |\n|    1_000 |  true |      2 |         2 |    414_617 µs |\n|    1_000 |  true |      2 |         4 |    446_155 µs |\n|    5_000 | false |      0 |         0 |  2_734_565 µs |\n|    5_000 | false |      2 |         0 |  3_450_438 µs |\n|    5_000 | false |      0 |         4 |  3_464_593 µs |\n|    5_000 |  true |      0 |         0 |  3_084_923 µs |\n|    5_000 |  true |      1 |         1 |  3_795_718 µs |\n|    5_000 |  true |      2 |         0 |  3_752_112 µs |\n|    5_000 |  true |      0 |         4 |  3_387_067 µs |\n|    5_000 |  true |      2 |         2 |  3_839_068 µs |\n|    5_000 |  true |      2 |         4 |  4_113_228 µs |\n|   10_000 | false |      0 |         0 |  6_889_505 µs |\n|   10_000 | false |      2 |         0 |  8_667_683 µs |\n|   10_000 | false |      0 |         4 |  8_606_961 µs |\n|   10_000 |  true |      0 |         0 |  7_892_421 µs |\n|   10_000 |  true |      1 |         1 |  8_449_838 µs |\n|   10_000 |  true |      2 |         0 |  9_507_693 µs |\n|   10_000 |  true |      0 |         4 | 10_339_080 µs |\n|   10_000 |  true |      2 |         2 | 10_518_744 µs |\n|   10_000 |  true |      2 |         4 | 10_480_884 µs |\n\n### Execution time\n\n| csv rows |  key | unique | filter_by |     by avg |    by tot | filter_by avg | filter_by tot |\n| -------: | ---: | -----: | --------: | ---------: | --------: | ------------: | ------------: |\n|    1_000 | true |      1 |         1 | 0.74 µs/op | 74_412 µs |    0.89 µs/op |     89_275 µs |\n|    5_000 | true |      1 |         1 | 0.79 µs/op | 79_776 µs |    1.18 µs/op |    118_786 µs |\n|   10_000 | true |      1 |         1 | 0.78 µs/op | 78_908 µs |    1.83 µs/op |    183_642 µs |\n\n### Execution details\nExecuted on my machine:\n\n    Lenovo Thinkpad T480\n    CPU: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz\n    RAM: 32GB\n\n### Try yourself\n\nIf you like to run compilation benchmarks yourself:\n\n```sh\niex -S mix\n```\n```elixir\nc \"benchmark/timings.exs\"\n```\n\n## Copyright and License\n\nCopyright (c) 2019 PrimaIt\n\nThis work is free. You can redistribute it and/or modify it under the\nterms of the MIT License. See the [LICENSE.md](./LICENSE.md) file for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprimait%2Fcsv_schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprimait%2Fcsv_schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprimait%2Fcsv_schema/lists"}