poison

An incredibly fast, pure Elixir JSON library

Github星跟蹤圖

Poison

Build Status
Coverage Status
Hex.pm Version
Hex.pm Download Total

Poison is a new JSON library for Elixir focusing on wicked-fast speed
without sacrificing simplicity, completeness, or correctness.

Poison takes several approaches to be the fastest JSON library for Elixir.

Poison uses extensive sub binary matching, a hand-rolled parser using
several techniques that are known to benefit HiPE for native compilation,
IO list encoding and single-pass decoding.

Poison benchmarks sometimes puts Poison's performance close to jiffy and
usually faster than other Erlang/Elixir libraries.

Poison fully conforms to RFC 7159, ECMA 404, and the
JSONTestSuite.

Installation

First, add Poison to your mix.exs dependencies:

def deps do
  [{:poison, "~> 3.1"}]
end

Then, update your dependencies:

$ mix deps.get

Usage

Poison.encode!(%{"age" => 27, "name" => "Devin Torres"})
#=> "{\"name\":\"Devin Torres\",\"age\":27}"

Poison.decode!(~s({"name": "Devin Torres", "age": 27}))
#=> %{"age" => 27, "name" => "Devin Torres"}

defmodule Person do
  @derive [Poison.Encoder]
  defstruct [:name, :age]
end

Poison.encode!(%Person{name: "Devin Torres", age: 27})
#=> "{\"name\":\"Devin Torres\",\"age\":27}"

Poison.decode!(~s({"name": "Devin Torres", "age": 27}), as: %Person{})
#=> %Person{name: "Devin Torres", age: 27}

Poison.decode!(~s({"people": [{"name": "Devin Torres", "age": 27}]}),
  as: %{"people" => [%Person{}]})
#=> %{"people" => [%Person{age: 27, name: "Devin Torres"}]}

Every component of Poison (encoder, decoder, and parser) are all usable on
their own without buying into other functionality. For example, if you were
interested purely in the speed of parsing JSON without a decoding step, you
could simply call Poison.Parser.parse.

Parser

iex> Poison.Parser.parse!(~s({"name": "Devin Torres", "age": 27}), %{})
%{"name" => "Devin Torres", "age" => 27}
iex> Poison.Parser.parse!(~s({"name": "Devin Torres", "age": 27}), %{keys: :atoms!})
%{name: "Devin Torres", age: 27}

Note that keys: :atoms! reuses existing atoms, i.e. if :name was not
allocated before the call, you will encounter an argument error message.

You can use the keys: :atoms variant to make sure all atoms are created as
needed. However, unless you absolutely know what you're doing, do not do
it. Atoms are not garbage-collected, see
Erlang Efficiency Guide
for more info:

Atoms are not garbage-collected. Once an atom is created, it will never be
removed. The emulator will terminate if the limit for the number of atoms
(1048576 by default) is reached.

Encoder

iex> Poison.Encoder.encode([1, 2, 3], %{}), > IO.iodata_to_binary
"[1,2,3]"

Anything implementing the Encoder protocol is expected to return an
IO list to be embedded within any other Encoder's implementation and
passable to any IO subsystem without conversion.

defimpl Poison.Encoder, for: Person do
  def encode(%{name: name, age: age}, options) do
    Poison.Encoder.BitString.encode("#{name} (#{age})", options)
  end
end

For maximum performance, make sure you @derive [Poison.Encoder] for any
struct you plan on encoding.

Encoding only some attributes

When deriving structs for encoding, it is possible to select or exclude
specific attributes. This is achieved by deriving Poison.Encoder with the
:only or :except options set:

defmodule PersonOnlyName do
  @derive {Poison.Encoder, only: [:name]}
  defstruct [:name, :age]
end

defmodule PersonWithoutName do
  @derive {Poison.Encoder, except: [:name]}
  defstruct [:name, :age]
end

In case both :only and :except keys are defined, the :except option is
ignored.

Key Validation

According to RFC 7159 keys in a JSON object should be unique. This is
enforced and resolved in different ways in other libraries. In the Ruby JSON
library for example, the output generated from encoding a hash with a duplicate
key (say one is a string, the other an atom) will include both keys. When
parsing JSON of this type, Chromium will override all previous values with the
final one.

Poison will generate JSON with duplicate keys if you attempt to encode a map
with atom and string keys whose encoded names would clash. If you'd like to
ensure that your generated JSON doesn't have this issue, you can pass the
strict_keys: true option when encoding. This will force the encoding to fail.

Note: Validating keys can cause a small performance hit.

iex> Poison.encode!(%{:foo => "foo1", "foo" => "foo2"}, strict_keys: true)
** (Poison.EncodeError) duplicate key found: :foo

Benchmarking

$ MIX_ENV=bench mix run bench/run.exs

Current Benchmarks

As of 2017-05-15 on a 2.8 GHz Intel Core i7:

## EncoderBench
benchmark name             iterations   average time
maps (jiffy)                   500000   7.88 µs/op
structs (Poison)               200000   9.46 µs/op
structs (Jazz)                 100000   15.43 µs/op
structs (JSX)                  100000   18.45 µs/op
maps (Poison)                  100000   19.45 µs/op
maps (Jazz)                    100000   21.61 µs/op
maps (JSX)                      50000   31.76 µs/op
maps (JSON)                     50000   34.08 µs/op
structs (JSON)                  50000   47.56 µs/op
strings (jiffy)                 10000   107.68 µs/op
lists (Poison)                  10000   120.79 µs/op
string escaping (jiffy)         10000   139.92 µs/op
lists (jiffy)                   10000   229.18 µs/op
lists (Jazz)                    10000   236.86 µs/op
strings (JSON)                  10000   237.97 µs/op
strings (JSX)                   10000   283.87 µs/op
lists (JSX)                      5000   336.96 µs/op
jiffy                            5000   429.92 µs/op
strings (Jazz)                   5000   430.78 µs/op
jiffy (pretty)                   5000   431.55 µs/op
lists (JSON)                     5000   559.31 µs/op
strings (Poison)                 5000   574.26 µs/op
string escaping (Jazz)           1000   1313.51 µs/op
string escaping (JSX)            1000   1474.66 µs/op
Poison                           1000   1546.53 µs/op
string escaping (Poison)         1000   1728.66 µs/op
Poison (pretty)                  1000   1784.37 µs/op
Jazz                             1000   2060.77 µs/op
JSON                             1000   2250.89 µs/op
JSX                              1000   2252.77 µs/op
Jazz (pretty)                    1000   2317.55 µs/op
JSX (pretty)                      500   5577.33 µs/op
## ParserBench
benchmark name             iterations   average time
UTF-8 unescaping (jiffy)        50000   60.05 µs/op
UTF-8 unescaping (Poison)       10000   112.53 µs/op
UTF-8 unescaping (JSX)          10000   282.83 µs/op
UTF-8 unescaping (JSON)          5000   469.26 µs/op
jiffy                            5000   479.07 µs/op
Poison                           5000   730.85 µs/op
JSX                              1000   1947.77 µs/op
JSON                              500   5175.11 µs/op
Issue 90 (jiffy)                  100   18864.70 µs/op
Issue 90 (Poison)                  50   50091.16 µs/op
Issue 90 (JSX)                     10   155975.20 µs/op
Issue 90 (JSON)                     1   1964860.00 µs/op

License

Poison is released under CC0-1.0.

主要指標

概覽
名稱與所有者facebookresearch/poincare-embeddings
主編程語言Python
編程語言Elixir (語言數: 3)
平台
許可證Other
所有者活动
創建於2018-01-19 18:53:04
推送於2024-07-25 10:14:43
最后一次提交
發布數1
最新版本名稱1.0 (發布於 )
第一版名稱1.0 (發布於 )
用户参与
星數1.7k
關注者數48
派生數233
提交數26
已啟用問題?
問題數70
打開的問題數26
拉請求數0
打開的拉請求數5
關閉的拉請求數12
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?