michalmuskala / jason

A blazing fast JSON parser and generator in pure Elixir.
Other
1.6k stars 170 forks source link

Request explanation: "By default all keys except the `:__struct__` key are encoded" #107

Closed i-n-g-m-a-r closed 3 years ago

i-n-g-m-a-r commented 4 years ago

By default all keys except the :__struct__ key are encoded

https://github.com/michalmuskala/jason/blob/c326c91f5a5d912b904661ed5e3c9e6cbf16162c/lib/encoder.ex#L14

Why are structs not encoded and decoded back into structs? What is wrong with {"__struct__":"Elixir.MyStruct"} ? Is it possible to easily override this default behaviour without implementing Jason.Encoder for every struct? And would it be possible for Jason.Decoder to automatically "deserialize" structs? Maybe the explanation could be part of the moduledoc.

chulkilee commented 4 years ago

Although it looks tempting... I think it opens up too many edge cases to this library.

I think it's better to leave Jason as dumb converter, and make application handle that.

michalmuskala commented 3 years ago

Jason has no default encoding for structs - implementation of the protocol is always required - the default you see there talks about the behaviour of the explicit derivation of the protocol. There's nothing that generally stops you from implementing the protocol yourself where __struct__ would be encoded.

One example of such implementation could be:

defmodule MyJasonHelpers do
  defmacro derive_protocol() do
    quote do
      defimpl Jason.Encoder do
        def encode(struct, opts), do: Jason.Encode.keyword(Map.to_list(struct), opts)
      end
    end
  end
end

This could later be used to derive the implementation, where this behaviour is desired:

defmodule MyStuct do
   require MyJasonHelpers

   MyJasonHelpers.derive_protocol()
   defstruct [:foo, :bar, ...]
end

Decoding back into complex data structures is not supported, since I think this is not a role for a low-level encoding library such as Jason. More often than not, there needs to be some sort of verification layer that makes sure the decoded data conforms to the invariants of various data structures - blindly deserialising data is usually very problematic. There are many libraries in the Elixir ecosystem that offer such tools, like ecto or norm.