• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

bench/H15-Jan-2017-1,6441,586

config/H15-Jan-2017-2722

lib/H15-Jan-2017-855683

test/H15-Jan-2017-491403

.editorconfigH A D15-Jan-2017271 1511

.gitignoreH A D15-Jan-201777 98

.travis.ymlH A D15-Jan-2017243 2524

LICENSEH A D15-Jan-20176.9 KiB122109

README.mdH A D15-Jan-20175.4 KiB166123

VERSIONH A D15-Jan-20176 21

mix.exsH A D15-Jan-20171.3 KiB4943

mix.lockH A D15-Jan-2017971 98

README.md

1# Poison
2
3[![Travis](https://img.shields.io/travis/devinus/poison.svg?style=flat-square)](https://travis-ci.org/devinus/poison)
4[![Hex.pm](https://img.shields.io/hexpm/v/poison.svg?style=flat-square)](https://hex.pm/packages/poison)
5[![Hex.pm](https://img.shields.io/hexpm/dt/poison.svg?style=flat-square)](https://hex.pm/packages/poison)
6[![Gratipay](https://img.shields.io/gratipay/devinus.svg?style=flat-square)](https://gratipay.com/devinus)
7
8Poison is a new JSON library for Elixir focusing on wicked-fast **speed**
9without sacrificing **simplicity**, **completeness**, or **correctness**.
10
11Poison takes several approaches to be the fastest JSON library for Elixir.
12
13Poison uses extensive [sub binary matching][1], a **hand-rolled parser** using
14several techniques that are [known to benefit HiPE][2] for native compilation,
15[IO list][3] encoding and **single-pass** decoding.
16
17Preliminary benchmarking has sometimes put Poison's performance closer to
18`jiffy`, and almost always faster than existing Elixir libraries.
19
20## Installation
21
22First, add Poison to your `mix.exs` dependencies:
23
24```elixir
25def deps do
26  [{:poison, "~> 3.0"}]
27end
28```
29
30Then, update your dependencies:
31
32```sh-session
33$ mix deps.get
34```
35
36## Usage
37
38```elixir
39defmodule Person do
40  @derive [Poison.Encoder]
41  defstruct [:name, :age]
42end
43
44Poison.encode!(%Person{name: "Devin Torres", age: 27})
45#=> "{\"name\":\"Devin Torres\",\"age\":27}"
46
47Poison.decode!(~s({"name": "Devin Torres", "age": 27}), as: %Person{})
48#=> %Person{name: "Devin Torres", age: 27}
49
50Poison.decode!(~s({"people": [{"name": "Devin Torres", "age": 27}]}),
51  as: %{"people" => [%Person{}]})
52#=> %{"people" => [%Person{age: 27, name: "Devin Torres"}]}
53```
54
55Every component of Poison -- the encoder, decoder, and parser -- are all usable
56on their own without buying into other functionality. For example, if you were
57interested purely in the speed of parsing JSON without a decoding step, you
58could simply call `Poison.Parser.parse`.
59
60If you use Poison 1.x, you have to set a module to `as` option in order to
61decode into a struct. e.g. `as: Person` instead of `as: %Person{}`. The change
62was introduced in 2.0.0.
63
64## Parser
65
66```iex
67iex> Poison.Parser.parse!(~s({"name": "Devin Torres", "age": 27}))
68%{"name" => "Devin Torres", "age" => 27}
69iex> Poison.Parser.parse!(~s({"name": "Devin Torres", "age": 27}), keys: :atoms!)
70%{name: "Devin Torres", age: 27}
71```
72
73Note that `keys: :atoms!` reuses existing atoms, i.e. if `:name` was not
74allocated before the call, you will encounter an `argument error` message.
75
76You can use the `keys: :atoms` variant to make sure all atoms are created as
77needed.  However, unless you absolutely know what you're doing, do **not** do
78it.  Atoms are not garbage-collected, see
79[Erlang Efficiency Guide](http://www.erlang.org/doc/efficiency_guide/commoncaveats.html)
80for more info:
81
82> Atoms are not garbage-collected. Once an atom is created, it will never be
83> removed. The emulator will terminate if the limit for the number of atoms
84> (1048576 by default) is reached.
85
86## Encoder
87
88```iex
89iex> IO.puts Poison.Encoder.encode([1, 2, 3], [])
90"[1,2,3]"
91```
92
93Anything implementing the Encoder protocol is expected to return an
94[IO list][4] to be embedded within any other Encoder's implementation and
95passable to any IO subsystem without conversion.
96
97```elixir
98defimpl Poison.Encoder, for: Person do
99  def encode(%{name: name, age: age}, options) do
100    Poison.Encoder.BitString.encode("#{name} (#{age})", options)
101  end
102end
103```
104
105For maximum performance, make sure you `@derive [Poison.Encoder]` for any struct
106you plan on encoding.
107
108### Encoding only some attributes
109
110When deriving structs for encoding, it is possible to select or exclude specific
111attributes. This is achieved by deriving `Poison.Encoder` with the `:only` or
112`:except` options set:
113
114```elixir
115defmodule PersonOnlyName do
116  @derive {Poison.Encoder, only: [:name]}
117  defstruct [:name, :age]
118end
119
120defmodule PersonWithoutName do
121  @derive {Poison.Encoder, except: [:name]}
122  defstruct [:name, :age]
123end
124```
125
126In case both `:only` and `:except` keys are defined, the `:except` option is
127ignored.
128
129### Key Validation
130
131According to [the JSON spec](https://tools.ietf.org/html/rfc7159#section-4) keys
132in a JSON object should be unique. This is enforced and resolved in different
133ways in other libraries. In the Ruby JSON library for example, the output
134generated from encoding a hash with a duplicate key (say one is a string, the
135other an atom) will include both keys. When parsing JSON of this type, Chromium
136will override all previous values with the final one.
137
138Like Ruby, Poison will also generate JSON with duplicate keys. If you'd like to
139ensure that your generated JSON doesn't have this issue, you can pass the
140`strict_keys: true` option when encoding. This will force the encoding to fail.
141
142Note that validating keys can cause a small performance hit.
143
144```iex
145iex> Poison.encode!(%{:foo => "foo1", "foo" => "foo2"}, strict_keys: true)
146** (Poison.EncodeError) duplicate key found: "foo"
147```
148
149## Benchmarking
150
151```sh-session
152$ mix deps.get
153$ MIX_ENV=bench mix compile
154$ MIX_ENV=bench mix bench
155```
156
157## License
158
159Poison is released under [CC0-1.0][5] (see `LICENSE`).
160
161[1]: http://www.erlang.org/euc/07/papers/1700Gustafsson.pdf
162[2]: http://www.erlang.org/workshop/2003/paper/p36-sagonas.pdf
163[3]: http://jlouisramblings.blogspot.com/2013/07/problematic-traits-in-erlang.html
164[4]: http://prog21.dadgum.com/70.html
165[5]: https://creativecommons.org/publicdomain/zero/1.0/
166