【问题标题】:Float format when json serializing in elixirjson在elixir中序列化时的浮点格式
【发布时间】:2018-03-15 18:17:36
【问题描述】:

默认情况下,Elixir 对大于 1000 的浮点数使用科学记数法。这会在 json 序列化过程中产生不良副作用。

iex(5)> val = 1000.00
1.0e3
iex(11)> Poison.encode(val)
{:ok, "1.0e3"}

我想要的输出是

iex(11)> Poison.encode(val)
{:ok, "1000.00"}

我见过this answer 使用:erlang.float_to_binary(0.005 * 2.7 / 100, [:compact, {:decimals, 10}]):io.format("~f~n",[0.005 * 2.7 / 100]),但这需要修补Poison 或在编码之前手动检查所有数据。

有没有一种更简洁的方法可以在 elixir 中强制将默认浮点数转换为二进制格式?

【问题讨论】:

  • Poison(或任何其他序列化程序)应该如何知道您希望留下多少尾随零?
  • 这不是关于尾随零,而是关于科学记数法1000.0 而不是1.0e3。而问题是如何定义我想要的格式?

标签: json elixir elixir-poison


【解决方案1】:

Poison 允许实现Poison.Encoder 协议。 Float 的实现显然是 exists,这就是为什么我建议将你的浮动包装到自定义 FloatStruct 中:

defmodule FloatStruct do
  defstruct value: 0.0, format: [:compact, {:decimals, 10}]
end

defimpl Poison.Encoder, for: FloatStruct do
  def encode(%{value: value, format: format}, options) do
    Poison.Encoder.BitString.encode(
      :erlang.float_to_binary(value, format), options)
  end
end

我知道这需要遍历嵌套术语以将Floats 与FloatStructs 包装起来,但我没有看到任何更简单的方法。不过,我可能错了。


可以免费支持 OP 格式中提到的这两种格式:

defimpl Poison.Encoder, for: FloatStruct do
  def encode(%{value: value, format: format}, options) do
    Poison.Encoder.BitString.encode(
      format(value, format), options)
  end

  defp format(value, format) when is_list(format),
    do: :erlang.float_to_binary(value, format)
  defp format(value, format) when is_binary(format),
    do: :io.format(format, [value])
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多