{"id":15056324,"url":"https://github.com/williamthome/json_polyfill","last_synced_at":"2025-04-10T04:07:39.207Z","repository":{"id":236946123,"uuid":"793506643","full_name":"williamthome/json_polyfill","owner":"williamthome","description":"A polyfill for the OTP json module (EEP68)","archived":false,"fork":false,"pushed_at":"2025-02-09T17:11:52.000Z","size":526,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T04:07:32.092Z","etag":null,"topics":["erlang","erlang-library","erlang-otp","json","json-decoder","json-encoder","polyfill"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/json_polyfill","language":"Erlang","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/williamthome.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-29T10:57:15.000Z","updated_at":"2025-04-02T04:59:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"14fd2980-4ab5-43eb-8073-7c76d30fc3bf","html_url":"https://github.com/williamthome/json_polyfill","commit_stats":null,"previous_names":["williamthome/json_polyfill"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamthome%2Fjson_polyfill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamthome%2Fjson_polyfill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamthome%2Fjson_polyfill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamthome%2Fjson_polyfill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/williamthome","download_url":"https://codeload.github.com/williamthome/json_polyfill/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248154986,"owners_count":21056543,"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","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":["erlang","erlang-library","erlang-otp","json","json-decoder","json-encoder","polyfill"],"created_at":"2024-09-24T21:49:56.132Z","updated_at":"2025-04-10T04:07:39.165Z","avatar_url":"https://github.com/williamthome.png","language":"Erlang","readme":"# json_polyfill\n\nThis lib is just a copy of the `json` module proposed in [EEP 68](https://www.erlang.org/eeps/eep-0068) and [introduced in OTP 27](https://www.erlang.org/news/168#highlights-for-rc2) by [Michał Muskała](https://github.com/michalmuskala).\n\nIts intent is to act as a polyfill for apps that cannot currently be updated to OTP 27 or higher.\n\nThe module and function names are exactly the same. Then, when your app supports OTP \u003e= 27, just optionally remove this lib from the dependencies.\n\n\u003e [!NOTE]\n\u003e\n\u003e There is no problem keeping this lib on OTP \u003e= 27 when using `rebar`. The `beam` file is dropped on compilation time.\n\n## Requirements\n\nOTP \u003e= 24.\n\n## Installation\n\n### Erlang\n\n```erlang\n% rebar.config\n{deps, [{json_polyfill, \"~\u003e 0.2\"}]}.\n```\n\n### Elixir\n\n```elixir\n# mix.exs\ndef deps do\n  [{:json_polyfill, \"~\u003e 0.2\"}]\nend\n```\n\n## Encode\n\n### encode/1\n\nGenerates JSON corresponding to `Term`.\n\nSupports basic data mapping:\n\n| **Erlang**             | **JSON** |\n|------------------------|----------|\n| `integer() \\| float()` | Number   |\n| `true \\| false `       | Boolean  |\n| `null`                 | Null     |\n| `binary()`             | String   |\n| `atom()`               | String   |\n| `list()`               | Array    |\n| `#{binary() =\u003e _}`     | Object   |\n| `#{atom() =\u003e _}`       | Object   |\n| `#{integer() =\u003e _}`    | Object   |\n\nThis is equivalent to `encode(Term, fun json:encode_value/2)`.\n\n#### Example\n\n```erlang\n\u003e iolist_to_binary(json:encode(#{foo =\u003e \u003c\u003c\"bar\"\u003e\u003e})).\n\u003c\u003c\"{\\\"foo\\\":\\\"bar\\\"}\"\u003e\u003e\n```\n\n### encode/2\n\nGenerates JSON corresponding to `Term`.\n\nCan be customised with the `Encoder` callback. The callback will be recursively called for all the data to be encoded and is expected to return the corresponding encoded JSON as iodata.\n\nVarious `encode_*` functions in this module can be used to help in constructing such callbacks.\n\n#### Example\n\nAn encoder that uses a heuristic to differentiate object-like lists of key-value pairs from plain lists:\n\n```erlang\n\u003e encoder([{_, _} | _] = Value, Encode) -\u003e json:encode_key_value_list(Value, Encode);\n\u003e encoder(Other, Encode) -\u003e json:encode_value(Other, Encode).\n\u003e custom_encode(Value) -\u003e json:encode(Value, fun(Value, Encode) -\u003e encoder(Value, Encode) end).\n\u003e iolist_to_binary(custom_encode([{a, []}, {b, 1}])).\n\u003c\u003c\"{\\\"a\\\":[],\\\"b\\\":1}\"\u003e\u003e\n```\n\n## Format\n\n### format/1\n\nGenerates formatted JSON corresponding to `Term`.\nSimiliar to `encode/1` but with added whitespaces for formatting.\n\n```erlang\n\u003e io:put_chars(json:format(#{foo =\u003e \u003c\u003c\"bar\"\u003e\u003e, baz =\u003e 52})).\n{\n  \"baz\": 52,\n  \"foo\": \"bar\"\n}\nok\n```\n\n### format/2\n\nGenerates formatted JSON corresponding to `Term`.\nEquivalent to `format(Term, fun json:format_value/3, Options)` or `format(Term, Encoder, #{})`.\n\n### format/3\n\nGenerates formatted JSON corresponding to `Term`.\nSimilar to `encode/2`, can be customised with the `Encoder` callback and `Options`.\n`Options` can include 'indent' to specify number of spaces per level and 'max' which loosely limits\nthe width of lists.\nThe `Encoder` will get a 'State' argument which contains the 'Options' maps merged with other data\nwhen recursing through 'Term'.\n`format_value/3` or various `encode_*` functions in this module can be used\nto help in constructing such callbacks.\n\n```erlang\n\u003e formatter({posix_time, SysTimeSecs}, Encode, State) -\u003e\n    TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, \"Z\"}]),\n    json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);\n\u003e formatter(Other, Encode, State) -\u003e json:format_value(Other, Encode, State).\n\u003e\n\u003e Fun = fun(Value, Encode, State) -\u003e formatter(Value, Encode, State) end.\n\u003e Options = #{indent =\u003e 4}.\n\u003e Term = #{id =\u003e 1, time =\u003e {posix_time, erlang:system_time(seconds)}}.\n\u003e\n\u003e io:put_chars(json:format(Term, Fun, Options)).\n{\n    \"id\": 1,\n    \"time\": \"2024-05-23T16:07:48Z\"\n}\nok\n```\n\n### format_value/3\n\nDefault format function used by `json:format/1`.\nRecursively calls `Encode` on all the values in `Value`,\nand indents objects and lists.\n\n### format_key_value_list/3\n\nFormat function for lists of key-value pairs as JSON objects.\nAccepts lists with atom, binary, integer, or float keys.\n\n### format_key_value_list_checked/3\n\n@doc Format function for lists of key-value pairs as JSON objects.\nAccepts lists with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.\n\n#### Errors\n\nRaises `error({duplicate_key, Key})` if there are duplicates.\n\n## Decode\n\n### decode/1\n\nParses a JSON value from `Binary`.\n\nSupports basic data mapping:\n\n| **JSON** | **Erlang**             |\n|----------|------------------------|\n| Number   | `integer() \\| float()` |\n| Boolean  | `true \\| false`        |\n| Null     | `null`                 |\n| String   | `binary()`             |\n| Object   | `#{binary() =\u003e _}`     |\n\n#### Errors\n\n* `error(unexpected_end)` if `Binary` contains incomplete JSON value\n* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({invalid_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape\n\n#### Example\n\n```erlang\n\u003e json:decode(\u003c\u003c\"{\\\"foo\\\": 1}\"\u003e\u003e).\n#{\u003c\u003c\"foo\"\u003e\u003e =\u003e 1}\n```\n\n### decode/3\n\nParses a JSON value from `Binary`.\n\nSimilar to `decode/1` except the decoding process can be customized with the callbacks specified in `Decoders`. The callbacks will use the `Acc` value as the initial accumulator.\n\nAny leftover, unparsed data in `Binary` will be returned.\n\n#### Default callbacks\n\nAll callbacks are optional. If not provided, they will fall back to implementations used by the `decode/1` function:\n\n* for `array_start`: `fun(_) -\u003e [] end`\n* for `array_push`: `fun(Elem, Acc) -\u003e [Elem | Acc] end`\n* for `array_finish`: `fun(Acc, OldAcc) -\u003e {lists:reverse(Acc), OldAcc} end`\n* for `object_start`: `fun(_) -\u003e [] end`\n* for `object_push`: `fun(Key, Value, Acc) -\u003e [{Key, Value} | Acc] end`\n* for `object_finish`: `fun(Acc, OldAcc) -\u003e {maps:from_list(Acc), OldAcc} end`\n* for `float`: `fun erlang:binary_to_float/1`\n* for `integer`: `fun erlang:binary_to_integer/1`\n* for `string`: `fun (Value) -\u003e Value end`\n* for `null`: the atom `null`\n\n#### Errors\n\n* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({invalid_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape\n* `error(unexpected_end)` if `Binary` contains incomplete JSON value\n\n#### Example\n\nDecoding object keys as atoms:\n\n```erlang\n\u003e Push = fun(Key, Value, Acc) -\u003e [{binary_to_existing_atom(Key), Value} | Acc] end.\n\u003e json:decode(\u003c\u003c\"{\\\"foo\\\": 1}\"\u003e\u003e, ok, #{object_push =\u003e Push}).\n{#{foo =\u003e 1},ok,\u003c\u003c\u003e\u003e}\n```\n\n## License\n\nErlang/OTP is released under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).\n\n\u003e %CopyrightBegin%\n\u003e\n\u003e Copyright Ericsson AB 2010-2024. All Rights Reserved.\n\u003e\n\u003e Licensed under the Apache License, Version 2.0 (the \"License\");\n\u003e you may not use this file except in compliance with the License.\n\u003e You may obtain a copy of the License at\n\u003e\n\u003e     http://www.apache.org/licenses/LICENSE-2.0\n\u003e\n\u003e Unless required by applicable law or agreed to in writing, software\n\u003e distributed under the License is distributed on an \"AS IS\" BASIS,\n\u003e WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\u003e See the License for the specific language governing permissions and\n\u003e limitations under the License.\n\u003e\n\u003e %CopyrightEnd%\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamthome%2Fjson_polyfill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilliamthome%2Fjson_polyfill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamthome%2Fjson_polyfill/lists"}