• Stars
    star
    1,975
  • Rank 22,378 (Top 0.5 %)
  • Language
    Elixir
  • License
    BSD Zero Clause L...
  • Created about 10 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An incredibly fast, pure Elixir JSON library

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 BeamAsm for JIT 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 fully passes the JSONTestSuite.

Installation

First, add Poison to your mix.exs dependencies:

def deps do
  [{:poison, "~> 5.0"}]
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 2021-07-22:

License

Poison is released under the public-domain-equivalent 0BSD license.

More Repositories

1

poolboy

A hunky Erlang worker pool factory
Erlang
1,503
star
2

sh

Run programs as functions in Elixir
Elixir
143
star
3

execjs

Run JavaScript code from Elixir
Elixir
143
star
4

markdown

A simple Elixir Markdown to HTML conversion library
C
85
star
5

detergent

An emulsifying Erlang SOAP library
Erlang
62
star
6

sqerl

An Erlang-flavoured SQL DSL
Erlang
58
star
7

html-autoprefixer

Autoprefix all CSS inside an html page - CSS inside style tags and inside style attributes.
JavaScript
54
star
8

walrus

Walrus - Mustache-like Templating
Erlang
44
star
9

fresh

The freshest Erlang web framework
Erlang
34
star
10

fotofoo

SproutCore foto foolery
JavaScript
28
star
11

zucchini

An Erlang INI parser
Erlang
27
star
12

clojure-box

An all-in-one installer for Clojure on Windows. Includes syntax highlighting and the REPL, plus enhanced editing with Slime and all of Emacs.
Emacs Lisp
18
star
13

genome

My genomic data
Standard ML
18
star
14

jsonex

JSON for Elixir
Elixir
8
star
15

epgsql_pool

Pooled epgsql connections using Poolboy
Erlang
7
star
16

confit

An Erlang configuration preserver
Erlang
6
star
17

sproutcore-couchdb

SproutCore CouchDB DataSource framework
JavaScript
6
star
18

cardio

A Cython wrapper around card.io
Python
5
star
19

poolboy-benchmark

A super flawed Poolboy benchmark
Erlang
5
star
20

static-site-brunch

Static site support for Brunch
JavaScript
4
star
21

jorge

A simple Erlang DSL for generating XML based on tuples of tuples
Erlang
4
star
22

kaolin

A C++ mud utilizing the STL (please don't judge. I was 15 when I wrote this and my knowledge of OO and patterns was embarrassing)
C++
3
star
23

jsonerl

yet another but slightly different erlang <-> json encoder/decoder
Erlang
3
star
24

peachfuzz

Simple Mustache inspired string substitution microlibrary
JavaScript
3
star
25

torix

TORres Interactive eXecution
C
3
star
26

dateutils

An erlang date manipulation library
Erlang
3
star
27

raiblocks-nodejs

RaiBlocks Node.js library
JavaScript
2
star
28

docker-elixir

Shell
2
star
29

virtio-wl-dkms

The virtio-wl kernel driver (DKMS)
C
2
star
30

kvc

Simple key-value coding for Elixir
Elixir
2
star
31

urlize

Python and PostgreSQL C extensions to urlize strings
C
2
star
32

metalsmith-html-postcss

Metalsmith plugin to process inline CSS in HTML using PostCSS
JavaScript
2
star
33

poison-textual-theme

Poison - A Textual Theme
JavaScript
2
star
34

docker-couchbase

Shell
2
star
35

docker-erlang

Shell
2
star
36

httpestle

Elixir
2
star
37

ember-skeleton

A skeleton application framework using Ember.js and Rake Pipeline
JavaScript
2
star
38

nano-docker

1
star
39

moonpool

Elixir
1
star
40

winked

A suggestive CommonJS linked list implementation
JavaScript
1
star
41

hemi

A Narwhal JavaScript engine
C++
1
star
42

raiblocks-docker

RaiBlocks node Docker definitions
1
star
43

devinus.github.io

HTML
1
star
44

starterkit

JavaScript
1
star
45

docker-minecraft

1
star
46

cloujin

Magical cloud rehosting
1
star
47

uuid4.js

JavaScript
1
star
48

resume

My resume
TeX
1
star
49

posthtml-when

PostHTML plugin for conditional plugins
JavaScript
1
star
50

dl_format_check

Verifies that a given drivers license fits that format for the state (a simple check of validity)
Elixir
1
star
51

canary

A passerine CommonJS binary search tree implementation
JavaScript
1
star
52

fooblock

Cross-browser ad blocker
1
star