elixirjson-deserializationplug

How to customise the options to the Plug.Parsers JSON decoder?


With Plug.Parsers, it is possible to configure the module that is used to parse JSON requests:

plug Plug.Parsers,
  parsers: [:json],
  json_decoder: Jason

However, with this syntax Jason.decode!/2 is called with an empty opts parameter.

How can we provide options to the specified json_decoder? For example, I would like to pass the keys: :atoms option to Jason.decode!/2.


Solution

  • As well as the module name, it's possible to pass a {Module, :function, args} tuple as the :json_decoder argument. This can be used to customise the arguments to the decoder:

    plug Plug.Parsers,
      parsers: [:json],
      json_decoder: {Jason, :decode!, [[keys: :atoms]]},
    

    This will result in the parser calling Jason.decode!(data, keys: :atoms).

    The [[]] list-in-a-list syntax is a bit strange, but it's necessary because of the way Plug.Parsers handles merging the options. For the same reason, an alternative way is to provide the empty list in the tuple, and include the option directly as an option to Plug.Parsers:

    plug Plug.Parsers,
      parsers: [:json],
      json_decoder: {Jason, :decode!, []},
      keys: :atoms
    

    I prefer the former because the options are better scoped, but the latter could be useful if some parsers share common parameters.