Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Elixir projects with Poison-style API #149

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions lib/jiffy.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
defmodule Jiffy do
@moduledoc """
A JSON parser as a NIF.

# Data Format

| Elixir | -> JSON | -> Elixir |
| ---------------------------- | ---------------- | ------- |
| `nil` | `null` | `nil` |
| `true` | `true` | `true` |
| `false` | `false` | `false` |
| `'hi'` | `[104, 105]` | `[104, 105]` |
| `"hi"` | `"hi"` | `"hi"` |
| `:hi` | `"hi"` | `"hi"` |
| `1` | `1` | `1` |
| `1.25` | `1.25` | `1.25` |
| `[]` | `[]` | `[]` |
| `[true, 1.0]` | `[true, 1.0]` | `[true, 1.0]` |
| `%{"foo" => "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
| `%{foo: "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
"""
@encode_options [:use_nil]
@decode_options [:use_nil, :return_maps]

@doc """
Encode a value to JSON.

# Unsupported structures

* Encoding Keywords currently is not supported.
* Encoding DateTime, Date or other Date-related Elixir structures will return
`{:error, {:invalid_ejson, any}}`. If you want to encode them - you need to cast
them to string before encoding.

# Options

* `:uescape` - Escapes UTF-8 sequences to produce a 7-bit clean output.
* `:pretty` - Produce JSON using two-space indentation.
* `:force_utf8` - Force strings to encode as UTF-8 by fixing broken
surrogate pairs and/or using the replacement character to remove
broken UTF-8 sequences in data.
* `:escape_forward_slashes` - Escapes the `/` character which can be
useful when encoding URLs in some cases.
* `{:bytes_per_red, n}` - Refer to the `decode/2` options.
* `{:bytes_per_iter, n}` - Refer to the `decode/2` options.

# Examples

iex> Jiffy.encode([1, 2, 3])
{:ok, "[1,2,3]"}
"""
@spec encode(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | {:error, any()}
def encode(data, opts \\ []) do
{:ok, encode!(data, opts)}
catch
{:error, reason} -> {:error, reason}
end

@doc """
Encode a value to JSON, raises an exception on error.

For list of options see `encode/2`.

# Examples

iex> Jiffy.encode!([1, 2, 3])
"[1,2,3]"
"""
@spec encode!(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | no_return()
def encode!(data, opts \\ []) do
data
|> :jiffy.encode(@encode_options ++ opts)
|> :erlang.iolist_to_binary()
end

@doc """
Decode JSON to a value.

# Options

* `:return_trailer` - If any non-whitespace is found after the first
JSON term is decoded the return value of decode/2 becomes
`{:has_trailer, first_term, rest_iodata}`. This is useful to
decode multiple terms in a single binary.
* `{:bytes_per_red, n}` where `n` >= 0 - This controls the number of
bytes that Jiffy will process as an equivalent to a reduction. Each
20 reductions we consume 1% of our allocated time slice for the current
process. When the Erlang VM indicates we need to return from the NIF.
* `{:bytes_per_iter, n}` where `n` >= 0 - Backwards compatible option
that is converted into the `bytes_per_red` value.

# Examples

iex> Jiffy.decode("[1,2,3]")
{:ok, [1, 2, 3]}
"""
@spec decode(String.t(), opts :: :jiffy.decode_option()) :: {:ok, any()} | {:error, atom()}
def decode(data, opts \\ []) do
{:ok, decode!(data, opts)}
catch
{:error, reason} -> {:error, reason}
end

@doc """
Decode JSON to a value, raises an exception on error.

For list of options see `decode/2`.

# Examples

iex> Jiffy.decode!("[1,2,3]")
[1, 2, 3]
"""
@spec decode!(String.t(), opts :: :jiffy.decode_option()) :: any() | no_return()
def decode!(data, opts \\ []) do
:jiffy.decode(data, @decode_options ++ opts)
end
end
39 changes: 39 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule Jiffy.Mixfile do
use Mix.Project

@version "0.14.11"

def project do
[app: :jiffy,
description: "A JSON parser as a NIF.",
package: package(),
version: @version,
compilers: [:elixir_make] ++ Mix.compilers(),
elixir: "~> 1.4",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps(),
docs: [source_ref: "v#\{@version\}", main: "readme", extras: ["README.md"]],
aliases: aliases()]
end

def application do
[extra_applications: [:logger]]
end

defp package do
[contributors: ["davisp"],
maintainers: ["davisp"],
licenses: ["MIT", "BSD"],
links: %{github: "https://github.com/davisp/jiffy"},
files: ~w(c_src src lib LICENSE mix.exs README.md)]
end

defp deps do
[{:elixir_make, "~> 0.4", runtime: false}]
end

defp aliases do
[clean: ["clean", "clean.make"]]
end
end
3 changes: 3 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
%{
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [:mix], [], "hexpm", "4549183795460c581fd82010d10862e46bcf796e2039d16c255bad3e408f435d"},
}