diff --git a/README.md b/README.md index 43d758b1..2f11a2d7 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,16 @@ iex> Poison.encode!(%{:foo => "foo1", "foo" => "foo2"}, strict_keys: true) ** (Poison.EncodeError) duplicate key found: :foo ``` +### 64bit Integers + +Some programming languages such as Javascript do not support 64bit integers. +You can pass the `bigint_to_string: true` option to convert it to string type. + +```iex +iex> Poison.encode!(4_294_967_296, %{bigint_to_string: true}) +"\"4294967296\"" +``` + ## Benchmarking ```sh-session diff --git a/lib/poison/encoder.ex b/lib/poison/encoder.ex index 6fec203d..152a109b 100644 --- a/lib/poison/encoder.ex +++ b/lib/poison/encoder.ex @@ -86,13 +86,15 @@ defprotocol Poison.Encoder do @typep indent :: non_neg_integer @typep offset :: non_neg_integer @typep strict_keys :: boolean + @typep bigint_to_string :: boolean @type options :: %{ optional(:escape) => escape, optional(:pretty) => pretty, optional(:indent) => indent, optional(:offset) => offset, - optional(:strict_keys) => strict_keys + optional(:strict_keys) => strict_keys, + optional(:bigint_to_string) => bigint_to_string } @spec encode(t, options) :: iodata @@ -221,8 +223,13 @@ defimpl Poison.Encoder, for: BitString do end defimpl Poison.Encoder, for: Integer do - def encode(integer, _options) do - Integer.to_string(integer) + def encode(integer, options) do + if Map.get(options, :bigint_to_string, false) && + (integer > 0xFFFFFFFF || integer < -0x80000000) do + integer |> Integer.to_string() |> Poison.Encoder.encode(options) + else + Integer.to_string(integer) + end end end diff --git a/test/poison/encoder_test.exs b/test/poison/encoder_test.exs index 4dd85c03..1bee5935 100644 --- a/test/poison/encoder_test.exs +++ b/test/poison/encoder_test.exs @@ -14,6 +14,17 @@ defmodule Poison.EncoderTest do assert to_json(42) == "42" end + test "BigInteger to string" do + assert to_json(0xFFFFFFFF + 1) == "#{0xFFFFFFFF + 1}" + assert to_json(-0x80000000 - 1) == "#{-0x80000000 - 1}" + + assert to_json(0xFFFFFFFF + 1, bigint_to_string: true) == + ~s("#{0xFFFFFFFF + 1}") + + assert to_json(-0x80000000 - 1, bigint_to_string: true) == + ~s("#{-0x80000000 - 1}") + end + test "Float" do assert to_json(99.99) == "99.99" assert to_json(9.9e100) == "9.9e100"