【问题标题】:Elixir - Nested JSON parsing to structsElixir - 嵌套 JSON 解析为结构
【发布时间】:2016-04-22 03:31:43
【问题描述】:

免责声明:我已经检查了here 的问题,但它没有回答我的问题。

我试图想出一种方法来解析 JSON 的嵌套结构。示例:

{"name": "blah blah", "address": {"street": "smthing"}}

我想达到这个结果:

%User{name: "blah blah", address: %Address{street: "smthing"}}

因为这样插入验证会更容易(例如使用Vex)。

我知道 Poison 支持“as struct”选项,但它不提供嵌套。以上将被解析:

%User{name: "blah blah", address: %{"street" => "smthing"}}. 

我知道我可以为模块 User 编写解码器实现,但我猜这不是预期的用例,它不会是通用的。

当我想知道一个实现时,我找不到一种方法来判断一个原子是否是一个模块......也许我必须选择:code.is_loaded(module_name)

无论如何,在尝试实现之前,我想知道是否有我没有看到的东西。

【问题讨论】:

    标签: json elixir


    【解决方案1】:

    我相信 Poison 现在可以实现上述目标:

    defmodule User do
      @derive [Poison.Encoder]
      defstruct [:address]
    end
    
    defmodule Address do
      @derive [Poison.Encoder]
      defstruct [:street]
    end
    
    Poison.decode(response, as: %User{address: %Address{}})
    

    【讨论】:

    • 这对 Poison 2.0 非常有用。谢谢@Maikon
    • 这是纯金,谢谢!
    【解决方案2】:

    目前,我知道的唯一选择是为Poison.Decoder(注意尾随r)协议提供您自己的实现。这有一个额外的好处,您可以在一个地方进行这些转换,只需写as: User 即可正确转换地址。例如:

    defimpl Poison.Decoder, for: User do
      def decode(task_list, options) do
        Map.update! task_list, :address, fn address ->
          Poison.Decode.decode(address, Keyword.merge(options, as: [Address]))
        end
      end
    end
    

    请注意,对decode 的内部调用不是来自Poison.Decoder,而是来自Poison.Decode,模块名称中没有尾随r。如果你用错了,你不会得到错误,它只是不起作用,调试起来很痛苦。

    从长远来看,我认为需要在 Poison 中做一些工作才能让所有这些使用起来更有趣。也许是一个宏,它可以更轻松地为自定义结构编写 Poison.Decoder 实现。也许还支持像as: %User{address: Address} 这样的嵌套结构选项,这应该不太难实现。另外我认为模块名称DecodeDecoder 太容易混淆,其中一个应该重命名。如果我有时间,也许我会提出这些建议并用 Poison 建立一个 PR。

    【讨论】:

    • 如果我这样做,也许更通用的方法是实现一个通用解码器,我会 use BaseDecoder 然后在 def __using__(_), do: etc 内部定义协议的实现。但是我必须知道一个原子是否是一个有效的模块,它是一个结构。
    • 我个人认为这有点太神奇了,但是嘿,为什么不 ;-) 当然这个设置可以简化,但我更喜欢更明确的方法。我为此开了一个 Github issue,让我们看看原作者是怎么想的,然后也许我会尝试实现它。 github.com/devinus/poison/issues/35
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-28
    • 2020-04-29
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    • 2018-04-10
    • 2015-01-15
    相关资源
    最近更新 更多