dependabot-hex 0.107.13 → 0.107.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/helpers/deps/jason/.fetch +0 -0
- data/helpers/deps/jason/.hex +2 -0
- data/helpers/deps/jason/CHANGELOG.md +60 -0
- data/helpers/deps/jason/LICENSE +13 -0
- data/helpers/deps/jason/README.md +179 -0
- data/helpers/deps/jason/hex_metadata.config +20 -0
- data/helpers/deps/jason/lib/codegen.ex +158 -0
- data/helpers/deps/jason/lib/decoder.ex +657 -0
- data/helpers/deps/jason/lib/encode.ex +630 -0
- data/helpers/deps/jason/lib/encoder.ex +216 -0
- data/helpers/deps/jason/lib/formatter.ex +253 -0
- data/helpers/deps/jason/lib/fragment.ex +11 -0
- data/helpers/deps/jason/lib/helpers.ex +90 -0
- data/helpers/deps/jason/lib/jason.ex +228 -0
- data/helpers/deps/jason/mix.exs +92 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdfcd650744ba2ee91ce3df24d3f52491cd67114662992284e4a5a25b225138a
|
4
|
+
data.tar.gz: d0fb29f7affd691ca9b4548352b4c760e5656edb42501c6a6d4c0ab126d01705
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30e28d4e7f5a7567f4e6b5832249ee46980d55d63194e1f222fd58fd7e207b5566874e3f718857c428e2c0e3c74f2bcd266fe1938312f8f5c3d299ff817c64a0
|
7
|
+
data.tar.gz: c9750bfdac7b2268a43f1f242da587f3b50240bac1cb54fd230138bd36acc5b6d785bf5b4e2dc22ce61639b8401ab34a5c62dc68c70e987d6cf8a7654e874778
|
File without changes
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 1.1.2 (19.10.2018)
|
4
|
+
|
5
|
+
### Bug fixes
|
6
|
+
|
7
|
+
* correctly handle the `pretty: false` option
|
8
|
+
([ba318c8](https://github.com/michalmuskala/jason/commit/ba318c8)).
|
9
|
+
|
10
|
+
## 1.1.1 (10.07.2018)
|
11
|
+
|
12
|
+
### Bug fixes
|
13
|
+
|
14
|
+
* correctly handle escape sequences in strings when pretty printing
|
15
|
+
([794bbe4](https://github.com/michalmuskala/jason/commit/794bbe4)).
|
16
|
+
|
17
|
+
## 1.1.0 (02.07.2018)
|
18
|
+
|
19
|
+
### Enhancements
|
20
|
+
|
21
|
+
* pretty-printing support through `Jason.Formatter` and `pretty: true` option
|
22
|
+
in `Jason.encode/2` ([d758e36](https://github.com/michalmuskala/jason/commit/d758e36)).
|
23
|
+
|
24
|
+
### Bug fixes
|
25
|
+
|
26
|
+
* silence variable warnings for fields with underscores used during deriving
|
27
|
+
([88dd85c](https://github.com/michalmuskala/jason/commit/88dd85c)).
|
28
|
+
* **potential incompatibility** don't raise `Protocol.UndefinedError` in non-bang functions
|
29
|
+
([ad0f57b](https://github.com/michalmuskala/jason/commit/ad0f57b)).
|
30
|
+
|
31
|
+
## 1.0.1 (02.07.2018)
|
32
|
+
|
33
|
+
### Bug fixes
|
34
|
+
|
35
|
+
* fix `Jason.Encode.escape` type ([a57b430](https://github.com/michalmuskala/jason/commit/a57b430))
|
36
|
+
* multiple documentation improvements
|
37
|
+
|
38
|
+
## 1.0.0 (26.01.2018)
|
39
|
+
|
40
|
+
No changes
|
41
|
+
|
42
|
+
## 1.0.0-rc.3 (26.01.2018)
|
43
|
+
|
44
|
+
### Changes
|
45
|
+
|
46
|
+
* update `escape` option of `Jason.encode/2` to take values:
|
47
|
+
`:json | :unicode_safe | :html_safe | :javascript_safe` for consistency. Old values of
|
48
|
+
`:unicode` and `:javascript` are still supported for compatibility with Poison.
|
49
|
+
([f42dcbd](https://github.com/michalmuskala/jason/commit/f42dcbd))
|
50
|
+
|
51
|
+
## 1.0.0-rc.2 (07.01.2018)
|
52
|
+
|
53
|
+
### Bug fixes
|
54
|
+
|
55
|
+
* add type for `strings` option ([b459ee4](https://github.com/michalmuskala/jason/commit/b459ee4))
|
56
|
+
* support iodata in `decode!` ([a1f3456](https://github.com/michalmuskala/jason/commit/a1f3456))
|
57
|
+
|
58
|
+
## 1.0.0-rc.1 (22.12.2017)
|
59
|
+
|
60
|
+
Initial release
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2017 Michał Muskała
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# Jason
|
2
|
+
|
3
|
+
A blazing fast JSON parser and generator in pure Elixir.
|
4
|
+
|
5
|
+
The parser and generator are at least twice as fast as other Elixir/Erlang libraries
|
6
|
+
(most notably `Poison`).
|
7
|
+
The performance is comparable to `jiffy`, which is implemented in C as a NIF.
|
8
|
+
Jason is usually only twice as slow.
|
9
|
+
|
10
|
+
Both parser and generator fully conform to
|
11
|
+
[RFC 8259](https://tools.ietf.org/html/rfc8259) and
|
12
|
+
[ECMA 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)
|
13
|
+
standards. The parser is tested using [JSONTestSuite](https://github.com/nst/JSONTestSuite).
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
The package can be installed by adding `jason` to your list of dependencies
|
18
|
+
in `mix.exs`:
|
19
|
+
|
20
|
+
```elixir
|
21
|
+
def deps do
|
22
|
+
[{:jason, "~> 1.1"}]
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
## Basic Usage
|
27
|
+
|
28
|
+
``` elixir
|
29
|
+
iex(1)> Jason.encode!(%{"age" => 44, "name" => "Steve Irwin", "nationality" => "Australian"})
|
30
|
+
"{\"age\":44,\"name\":\"Steve Irwin\",\"nationality\":\"Australian\"}"
|
31
|
+
|
32
|
+
iex(2)> Jason.decode!(~s({"age":44,"name":"Steve Irwin","nationality":"Australian"}))
|
33
|
+
%{"age" => 44, "name" => "Steve Irwin", "nationality" => "Australian"}
|
34
|
+
```
|
35
|
+
|
36
|
+
Full documentation can be found at [https://hexdocs.pm/jason](https://hexdocs.pm/jason).
|
37
|
+
|
38
|
+
## Use with other libraries
|
39
|
+
|
40
|
+
### Postgrex
|
41
|
+
|
42
|
+
You need to define a custom "types" module in an `.ex` file, somewhere in `lib`:
|
43
|
+
|
44
|
+
```elixir
|
45
|
+
Postgrex.Types.define(MyApp.PostgresTypes, [], json: Jason)
|
46
|
+
|
47
|
+
## If using with ecto, you also need to pass ecto default extensions:
|
48
|
+
|
49
|
+
Postgrex.Types.define(MyApp.PostgresTypes, [] ++ Ecto.Adapters.Postgres.extensions(), json: Jason)
|
50
|
+
```
|
51
|
+
|
52
|
+
Then you can use the module, by passing it to `Postgrex.start_link`.
|
53
|
+
### Ecto
|
54
|
+
|
55
|
+
To replicate fully the current behaviour of `Poison` when used in Ecto applications,
|
56
|
+
you need to configure `Jason` to be the default encoder in `config/config.exs`:
|
57
|
+
|
58
|
+
```elixir
|
59
|
+
config :ecto, json_library: Jason
|
60
|
+
```
|
61
|
+
|
62
|
+
Additionally, when using PostgreSQL, you need to define a custom types module as described
|
63
|
+
above, and configure your repo to use it (in either `config/config.exs` or `config/<env>.exs`):
|
64
|
+
|
65
|
+
```elixir
|
66
|
+
config :my_app, MyApp.Repo, types: MyApp.PostgresTypes
|
67
|
+
```
|
68
|
+
|
69
|
+
### Plug (and Phoenix)
|
70
|
+
|
71
|
+
First, you need to configure `Plug.Parsers` to use `Jason` for parsing JSON. You need to find,
|
72
|
+
where you're plugging the `Plug.Parsers` plug (in case of Phoenix, it will be in the
|
73
|
+
Endpoint module) and configure it in your endpoint module (`lib/app_web/endpoint.ex`),
|
74
|
+
for example:
|
75
|
+
|
76
|
+
```elixir
|
77
|
+
plug Plug.Parsers,
|
78
|
+
parsers: [:urlencoded, :multipart, :json],
|
79
|
+
pass: ["*/*"],
|
80
|
+
json_decoder: Jason
|
81
|
+
```
|
82
|
+
|
83
|
+
Additionally, for Phoenix, you need to configure the "encoder" in `config/config.exs`:
|
84
|
+
|
85
|
+
```elixir
|
86
|
+
config :phoenix, :format_encoders,
|
87
|
+
json: Jason
|
88
|
+
```
|
89
|
+
|
90
|
+
A custom JSON encoder for Phoenix channels is unfortunately a bit more involved,
|
91
|
+
you can find code for a custom serializer and how to use it [in here](https://gist.github.com/michalmuskala/d5fabcd26be2befdfb72b72e0b0f2797).
|
92
|
+
|
93
|
+
### Absinthe
|
94
|
+
|
95
|
+
You need to pass the `:json_codec` option to `Absinthe.Plug`
|
96
|
+
|
97
|
+
```elixir
|
98
|
+
# When called directly:
|
99
|
+
plug Absinthe.Plug,
|
100
|
+
schema: MyApp.Schema,
|
101
|
+
json_codec: Jason
|
102
|
+
|
103
|
+
# When used in phoenix router:
|
104
|
+
forward "/api",
|
105
|
+
to: Absinthe.Plug,
|
106
|
+
init_opts: [schema: MyApp.Schema, json_codec: Jason]
|
107
|
+
```
|
108
|
+
|
109
|
+
## Benchmarks
|
110
|
+
|
111
|
+
Detailed benchmarks (including memory measurements):
|
112
|
+
https://gist.github.com/michalmuskala/4d64a5a7696ca84ac7c169a0206640d5
|
113
|
+
|
114
|
+
HTML reports for the benchmark (only performance measurements):
|
115
|
+
http://michal.muskala.eu/jason/decode.html and http://michal.muskala.eu/jason/encode.html
|
116
|
+
|
117
|
+
### Running
|
118
|
+
|
119
|
+
Benchmarks against most popular Elixir & Erlang json libraries can be executed
|
120
|
+
with `mix bench.encode` and `mix bench.decode`.
|
121
|
+
A HTML report of the benchmarks (after their execution) can be found in
|
122
|
+
`bench/output/encode.html` and `bench/output/decode.html` respectively.
|
123
|
+
|
124
|
+
## Differences to Poison
|
125
|
+
|
126
|
+
Jason has a couple feature differences compared to Poison.
|
127
|
+
|
128
|
+
* Jason follows the JSON spec more strictly, for example it does not allow
|
129
|
+
unescaped newline characters in JSON strings - e.g. `"\"\n\""` will
|
130
|
+
produce a decoding error.
|
131
|
+
* no support for decoding into data structures (the `as:` option).
|
132
|
+
* no built-in encoders for `MapSet`, `Range` and `Stream`.
|
133
|
+
* no support for encoding arbitrary structs - explicit implementation
|
134
|
+
of the `Jason.Encoder` protocol is always required.
|
135
|
+
* different pretty-printing customisation options (default `pretty: true` works the same)
|
136
|
+
|
137
|
+
If you require encoders for any of the unsupported collection types, I suggest
|
138
|
+
adding the needed implementations directly to your project:
|
139
|
+
|
140
|
+
```elixir
|
141
|
+
defimpl Jason.Encoder, for: [MapSet, Range, Stream] do
|
142
|
+
def encode(struct, opts) do
|
143
|
+
Jason.Encode.list(Enum.to_list(struct), opts)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
If you need to encode some struct that does not implement the protocol,
|
149
|
+
if you own the struct, you can derive the implementation specifying
|
150
|
+
which fields should be encoded to JSON:
|
151
|
+
|
152
|
+
```elixir
|
153
|
+
@derive {Jason.Encoder, only: [....]}
|
154
|
+
defstruct # ...
|
155
|
+
```
|
156
|
+
|
157
|
+
It is also possible to encode all fields, although this should be
|
158
|
+
used carefully to avoid accidentally leaking private information
|
159
|
+
when new fields are added:
|
160
|
+
|
161
|
+
```elixir
|
162
|
+
@derive Jason.Encoder
|
163
|
+
defstruct # ...
|
164
|
+
```
|
165
|
+
|
166
|
+
Finally, if you don't own the struct you want to encode to JSON,
|
167
|
+
you may use `Protocol.derive/3` placed outside of any module:
|
168
|
+
|
169
|
+
```elixir
|
170
|
+
Protocol.derive(Jason.Encoder, NameOfTheStruct, only: [...])
|
171
|
+
Protocol.derive(Jason.Encoder, NameOfTheStruct)
|
172
|
+
```
|
173
|
+
|
174
|
+
## License
|
175
|
+
|
176
|
+
Jason is released under the Apache 2.0 License - see the [LICENSE](LICENSE) file.
|
177
|
+
|
178
|
+
Some elements of tests and benchmarks have their origins in the
|
179
|
+
[Poison library](https://github.com/devinus/poison) and were initially licensed under [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{<<"app">>,<<"jason">>}.
|
2
|
+
{<<"build_tools">>,[<<"mix">>]}.
|
3
|
+
{<<"description">>,
|
4
|
+
<<"A blazing fast JSON parser and generator in pure Elixir.">>}.
|
5
|
+
{<<"elixir">>,<<"~> 1.4">>}.
|
6
|
+
{<<"files">>,
|
7
|
+
[<<"lib">>,<<"lib/codegen.ex">>,<<"lib/decoder.ex">>,<<"lib/encode.ex">>,
|
8
|
+
<<"lib/encoder.ex">>,<<"lib/formatter.ex">>,<<"lib/fragment.ex">>,
|
9
|
+
<<"lib/helpers.ex">>,<<"lib/jason.ex">>,<<"mix.exs">>,<<"README.md">>,
|
10
|
+
<<"LICENSE">>,<<"CHANGELOG.md">>]}.
|
11
|
+
{<<"licenses">>,[<<"Apache 2.0">>]}.
|
12
|
+
{<<"links">>,[{<<"GitHub">>,<<"https://github.com/michalmuskala/jason">>}]}.
|
13
|
+
{<<"name">>,<<"jason">>}.
|
14
|
+
{<<"requirements">>,
|
15
|
+
[[{<<"app">>,<<"decimal">>},
|
16
|
+
{<<"name">>,<<"decimal">>},
|
17
|
+
{<<"optional">>,true},
|
18
|
+
{<<"repository">>,<<"hexpm">>},
|
19
|
+
{<<"requirement">>,<<"~> 1.0">>}]]}.
|
20
|
+
{<<"version">>,<<"1.1.2">>}.
|
@@ -0,0 +1,158 @@
|
|
1
|
+
defmodule Jason.Codegen do
|
2
|
+
@moduledoc false
|
3
|
+
|
4
|
+
alias Jason.{Encode, EncodeError}
|
5
|
+
|
6
|
+
def jump_table(ranges, default) do
|
7
|
+
ranges
|
8
|
+
|> ranges_to_orddict()
|
9
|
+
|> :array.from_orddict(default)
|
10
|
+
|> :array.to_orddict()
|
11
|
+
end
|
12
|
+
|
13
|
+
def jump_table(ranges, default, max) do
|
14
|
+
ranges
|
15
|
+
|> ranges_to_orddict()
|
16
|
+
|> :array.from_orddict(default)
|
17
|
+
|> resize(max)
|
18
|
+
|> :array.to_orddict()
|
19
|
+
end
|
20
|
+
|
21
|
+
defmacro bytecase(var, do: clauses) do
|
22
|
+
{ranges, default, literals} = clauses_to_ranges(clauses, [])
|
23
|
+
|
24
|
+
jump_table = jump_table(ranges, default)
|
25
|
+
|
26
|
+
quote do
|
27
|
+
case unquote(var) do
|
28
|
+
unquote(jump_table_to_clauses(jump_table, literals))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
defmacro bytecase(var, max, do: clauses) do
|
34
|
+
{ranges, default, empty} = clauses_to_ranges(clauses, [])
|
35
|
+
|
36
|
+
jump_table = jump_table(ranges, default, max)
|
37
|
+
|
38
|
+
quote do
|
39
|
+
case unquote(var) do
|
40
|
+
unquote(jump_table_to_clauses(jump_table, empty))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_kv_iodata(kv, encode_args) do
|
46
|
+
elements =
|
47
|
+
kv
|
48
|
+
|> Enum.map(&encode_pair(&1, encode_args))
|
49
|
+
|> Enum.intersperse(",")
|
50
|
+
|
51
|
+
collapse_static(List.flatten(["{", elements] ++ '}'))
|
52
|
+
end
|
53
|
+
|
54
|
+
defp clauses_to_ranges([{:->, _, [[{:in, _, [byte, range]}, rest], action]} | tail], acc) do
|
55
|
+
clauses_to_ranges(tail, [{range, {byte, rest, action}} | acc])
|
56
|
+
end
|
57
|
+
|
58
|
+
defp clauses_to_ranges([{:->, _, [[default, rest], action]} | tail], acc) do
|
59
|
+
{Enum.reverse(acc), {default, rest, action}, literal_clauses(tail)}
|
60
|
+
end
|
61
|
+
|
62
|
+
defp literal_clauses(clauses) do
|
63
|
+
Enum.map(clauses, fn {:->, _, [[literal], action]} ->
|
64
|
+
{literal, action}
|
65
|
+
end)
|
66
|
+
end
|
67
|
+
|
68
|
+
defp jump_table_to_clauses([{val, {{:_, _, _}, rest, action}} | tail], empty) do
|
69
|
+
quote do
|
70
|
+
<<unquote(val), unquote(rest)::bits>> ->
|
71
|
+
unquote(action)
|
72
|
+
end ++ jump_table_to_clauses(tail, empty)
|
73
|
+
end
|
74
|
+
|
75
|
+
defp jump_table_to_clauses([{val, {byte, rest, action}} | tail], empty) do
|
76
|
+
quote do
|
77
|
+
<<unquote(byte), unquote(rest)::bits>> when unquote(byte) === unquote(val) ->
|
78
|
+
unquote(action)
|
79
|
+
end ++ jump_table_to_clauses(tail, empty)
|
80
|
+
end
|
81
|
+
|
82
|
+
defp jump_table_to_clauses([], literals) do
|
83
|
+
Enum.flat_map(literals, fn {pattern, action} ->
|
84
|
+
quote do
|
85
|
+
unquote(pattern) ->
|
86
|
+
unquote(action)
|
87
|
+
end
|
88
|
+
end)
|
89
|
+
end
|
90
|
+
|
91
|
+
defmacro jump_table_case(var, rest, ranges, default) do
|
92
|
+
clauses =
|
93
|
+
ranges
|
94
|
+
|> jump_table(default)
|
95
|
+
|> Enum.flat_map(fn {byte_value, action} ->
|
96
|
+
quote do
|
97
|
+
<<unquote(byte_value), unquote(rest)::bits>> ->
|
98
|
+
unquote(action)
|
99
|
+
end
|
100
|
+
end)
|
101
|
+
|
102
|
+
clauses = clauses ++ quote(do: (<<>> -> empty_error(original, skip)))
|
103
|
+
|
104
|
+
quote do
|
105
|
+
case unquote(var) do
|
106
|
+
unquote(clauses)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
defp resize(array, size), do: :array.resize(size, array)
|
112
|
+
|
113
|
+
defp ranges_to_orddict(ranges) do
|
114
|
+
ranges
|
115
|
+
|> Enum.flat_map(fn
|
116
|
+
{int, value} when is_integer(int) ->
|
117
|
+
[{int, value}]
|
118
|
+
|
119
|
+
{enum, value} ->
|
120
|
+
Enum.map(enum, &{&1, value})
|
121
|
+
end)
|
122
|
+
|> :orddict.from_list()
|
123
|
+
end
|
124
|
+
|
125
|
+
defp encode_pair({key, value}, encode_args) do
|
126
|
+
key = IO.iodata_to_binary(Encode.key(key, &escape_key/3))
|
127
|
+
key = "\"" <> key <> "\":"
|
128
|
+
[key, quote(do: Encode.value(unquote(value), unquote_splicing(encode_args)))]
|
129
|
+
end
|
130
|
+
|
131
|
+
defp escape_key(binary, _original, _skip) do
|
132
|
+
check_safe_key!(binary)
|
133
|
+
binary
|
134
|
+
end
|
135
|
+
|
136
|
+
defp check_safe_key!(binary) do
|
137
|
+
for <<(<<byte>> <- binary)>> do
|
138
|
+
if byte > 0x7F or byte < 0x1F or byte in '"\\/' do
|
139
|
+
raise EncodeError,
|
140
|
+
"invalid byte #{inspect(byte, base: :hex)} in literal key: #{inspect(binary)}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
:ok
|
145
|
+
end
|
146
|
+
|
147
|
+
defp collapse_static([bin1, bin2 | rest]) when is_binary(bin1) and is_binary(bin2) do
|
148
|
+
collapse_static([bin1 <> bin2 | rest])
|
149
|
+
end
|
150
|
+
|
151
|
+
defp collapse_static([other | rest]) do
|
152
|
+
[other | collapse_static(rest)]
|
153
|
+
end
|
154
|
+
|
155
|
+
defp collapse_static([]) do
|
156
|
+
[]
|
157
|
+
end
|
158
|
+
end
|