{"id":26964456,"url":"https://github.com/nicklayb/starchoice","last_synced_at":"2025-10-30T05:11:52.811Z","repository":{"id":42626055,"uuid":"314702220","full_name":"nicklayb/starchoice","owner":"nicklayb","description":"Starchoice is a decoder library","archived":false,"fork":false,"pushed_at":"2024-06-04T13:09:14.000Z","size":50,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-10T22:05:57.754Z","etag":null,"topics":["decoders","json-decoders","maps"],"latest_commit_sha":null,"homepage":"","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/nicklayb.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":"2020-11-21T00:36:50.000Z","updated_at":"2025-04-10T12:24:17.000Z","dependencies_parsed_at":"2025-04-03T06:42:17.824Z","dependency_job_id":null,"html_url":"https://github.com/nicklayb/starchoice","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nicklayb/starchoice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicklayb%2Fstarchoice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicklayb%2Fstarchoice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicklayb%2Fstarchoice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicklayb%2Fstarchoice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicklayb","download_url":"https://codeload.github.com/nicklayb/starchoice/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicklayb%2Fstarchoice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281748716,"owners_count":26554822,"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-30T02:00:06.501Z","response_time":61,"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":["decoders","json-decoders","maps"],"created_at":"2025-04-03T06:31:36.316Z","updated_at":"2025-10-30T05:11:52.788Z","avatar_url":"https://github.com/nicklayb.png","language":"Elixir","funding_links":["https://ko-fi.com/D1D2YX9OU"],"categories":[],"sub_categories":[],"readme":"# Starchoice\n\n[![Build Status](https://circleci.com/gh/nicklayb/starchoice.svg?style=svg)](https://circleci.com/gh/nicklayb/starchoice.svg)\n[![Coverage Status](https://coveralls.io/repos/github/nicklayb/starchoice/badge.svg?branch=master)](https://coveralls.io/github/nicklayb/starchoice?branch=master)\n[![Module Version](https://img.shields.io/hexpm/v/starchoice.svg)](https://hex.pm/packages/starchoice)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/starchoice/)\n[![Total Download](https://img.shields.io/hexpm/dt/starchoice.svg)](https://hex.pm/packages/starchoice)\n[![License](https://img.shields.io/hexpm/l/starchoice.svg)](https://github.com/nicklayb/starchoice/blob/master/LICENSE)\n[![Last Updated](https://img.shields.io/github/last-commit/nicklayb/starchoice.svg)](https://github.com/nicklayb/starchoice/commits/master)\n\n\u003c!-- MDOC !--\u003e\n\nStarchoice takes his name from the satellite TV company (now called [Shaw Direct](https://en.wikipedia.org/wiki/Shaw_Direct)) because they are selling TV decoders. Since this lib is used to declare map decoders, I thought it felt appropriate to be named that way. Maybe not. Anyway.\n\nThe goal of the library is to provide a streamline process for converting String keyed maps to well defined structures. It is highly inspired by [Elm](https://elm-lang.org/)'s JSON decoders where you create different JSON decoders for the same data type.\n\nFor more information about creating decoder, visit the `Starchoice.Decoder` module documentation.\n\n\u003c!-- MDOC !--\u003e\n\n## Installation\n\n```elixir\ndef deps do\n  [\n    {:starchoice, \"~\u003e 0.3.0\"}\n  ]\nend\n```\n\n## Basic usage\n\nExamples:\n- [Snowhite](https://github.com/nicklayb/snowhite/tree/master/lib/open_weather): Snowhite uses Starchoice to decode HTTP responses from APIs.\n\n### Define decoders\n\nYou can define decoders in your struct's module by doing the following (this is the macro approach).\n\n```elixir\ndefmodule User do\n  defstruct email: nil, password: nil, profile: nil, permissions: []\n  use Starchoice.Decoder\n\n  defdecoder do\n    field(:email, with: \u0026String.downcase/1)\n    field(:password)\n    field(:profile, with: Profile)\n    field(:permissions, with: {Permission, :simple})\n  end\n\n  defdecoder :simple do\n    field(:email)\n  end\nend\n\ndefmodule Profile do\n  defstruct address: nil\n\n  defdecoder do\n    field(:address)\n  end\nend\n\ndefmodule Permission do\n  defstruct name: nil, access: nil\n\n  defdecoder :simple do\n    field(:name)\n    field(:access, with: \u0026Permission.decode_access/1)\n  end\n\n  def decode_access(\"r\"), do: :read\n  def decode_access(\"w\"), do: :write\n  def decode_access(\"rw\"), do: :full\nend\n```\n\nWe can now easily decode map payloads:\n\n```elixir\ninput = %{\n  \"email\" =\u003e \"NICOLAS@nboisvert.com\",\n  \"password\" =\u003e \"noneofyourbusiness\",\n  \"profile\" =\u003e %{\n    \"address\" =\u003e \"Somewhere str.\"\n  },\n  \"permissions\" =\u003e [\n    %{\"name\" =\u003e \"Articles\", \"access\" =\u003e \"rw\"}\n    %{\"name\" =\u003e \"Settings\", \"access\" =\u003e \"r\"}\n  ]\n}\n{:ok, decoded} = Starchoice.decode(input, User)\n%User{\n  email: \"nicolas@nboisvert.com\",\n  password: \"noneofyourbusiness\",\n  profile: %Profile{\n    address: \"Somewhere str.\"\n  },\n  permissions: [\n    %Permission{name: \"Articles\", access: :full},\n    %Permission{name: \"Settings\", access: :read},\n  ]\n}\n```\n\nThe basic of this can easily be achieved by using Ecto. However, for building a HTTP client or packaging lib, it might be a bit overkill to import a whole library like Ecto. This lightweight package can be pretty handy and is quite extensible.\n\n## Polymorphic decoding\n\nThis is something that might become helpful. Have for an instance, an API that returns every results under a `results` key like `{\"results\": [{}, {}, ...]}`. It would be pretty useful to have a polymorphic decoder. It is supported out of the box by doing the following:\n\n```elixir\ndefmodule Results do\n  defstruct results: []\n\n  def decoder(sub_type) do\n    __MODULE__\n    |\u003e Starchoice.Decoder.new()\n    |\u003e Starchoice.Decoder.put_field(:results, sub_type)\n  end\nend\n```\n\nThen you can use it like that:\n\n```elixir\ninput = %{\"results\" =\u003e [%{\"email\" =\u003e \"email@email.com\"}, %{\"email\" =\u003e \"another_email@email.com\"}]}\nStarchoice.decode(input, Results.decoder({User, :simple})) # this uses the :simple decoder defined for User before.\n%Results{\n  results: %{\n    %User{email: \"email@email.com\"},\n    %User{email: \"another_email@email.com\"},\n  }\n}\n```\n\n\n## License\n\nThis source code is licensed under the [MIT license](https://github.com/nicklayb/starchoice/blob/master/LICENSE). Copyright (c) 2020-present Nicolas Boisvert.\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/D1D2YX9OU)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicklayb%2Fstarchoice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicklayb%2Fstarchoice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicklayb%2Fstarchoice/lists"}