How to add an item to a list that is in a map without my database throwing an error

I have a json postgresql column that contains a map of things.
I am adding a new list in the map under a key, e.g.: “key1”

I append a map into a list of maps like so:
{:ok, old_list ++ new_map}

New list:

%{"key1" => [
  %{
    "num" => "0",
    "date" => "2022-03-30T11:00:51.907317+01:00",
    "description" => %{changed: :no_change}
  } |
  %{
    "date" => "2022-11-22T11:04:07.712875+00:00",
    "num" => 1,
    "description" => %{changed: :map_change, value: %{"num" => 0}}
  }
]
, ...}

I am recieving this error when trying to update the database record:

** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Jason.Encode.list_loop/3
        (jason 1.3.0) lib/encode.ex:149: Jason.Encode.list_loop(%{:date => "2022-11-22T11:04:07.712875+00:00", :num => 1, "description" => %{changed: :map_change, value: %{"num" => 0}}}, #Function<3.53305732/3 in Jason.Encode.escape_json>, #Function<1.53305732/3 in Jason.Encode.map_naive>)
        (jason 1.3.0) lib/encode.ex:146: Jason.Encode.list/3
        (jason 1.3.0) lib/encode.ex:184: Jason.Encode.map_naive_loop/3
        (jason 1.3.0) lib/encode.ex:185: Jason.Encode.map_naive_loop/3
        (jason 1.3.0) lib/encode.ex:175: Jason.Encode.map_naive/3
        (jason 1.3.0) lib/encode.ex:37: Jason.Encode.encode/2
        (jason 1.3.0) lib/jason.ex:211: Jason.encode_to_iodata!/2
        (postgrex 0.15.13) lib/postgrex/type_module.ex:897: Postgrex.DefaultTypes.encode_params/3
        (postgrex 0.15.13) lib/postgrex/query.ex:75: DBConnection.Query.Postgrex.Query.encode/3
        (db_connection 2.4.1) lib/db_connection.ex:1224: DBConnection.encode/5
        (db_connection 2.4.1) lib/db_connection.ex:1324: DBConnection.run_prepare_execute/5
        (db_connection 2.4.1) lib/db_connection.ex:1428: DBConnection.run/6
        (db_connection 2.4.1) lib/db_connection.ex:593: DBConnection.parsed_prepare_execute/5
        (db_connection 2.4.1) lib/db_connection.ex:585: DBConnection.prepare_execute/4
        (postgrex 0.15.13) lib/postgrex.ex:292: Postgrex.query/4
        (ecto_sql 3.7.0) lib/ecto/adapters/sql.ex:794: Ecto.Adapters.SQL.struct/10
        (ecto 3.7.1) lib/ecto/repo/schema.ex:744: Ecto.Repo.Schema.apply/4
        (ecto 3.7.1) lib/ecto/repo/schema.ex:451: anonymous fn/15 in Ecto.Repo.Schema.do_update/4
        (absinthe 1.6.6) lib/absinthe/resolution.ex:209: Absinthe.Resolution.call/2

Is this because of my use of ++ when trying to append an item to my list?
Postgres doesn’t like the | notation in the list?

I think this is an ecto bug edit: not a bug around the usage of | when concatenating a list.

I changed my code to Enum.concat(old_list, [new_map]) and it worked perfectly fine, will raise this as a bug in the Ecto library edit: and got correct by the man Jose Valim himself.

It’s not a bug. list ++ new_map gives you […items | map], which is an improper list - they’re something useful in some places, but no longer a normal list. ++ is not an append operator, but for list concatination. Switching to list ++ [map] (resulting in […items, map]), just like you did a bit more explicitly with Enum.concat would be the correct use of the operator here.

2 Likes

I see, thank you for teaching me this.

Here is the issue EddTally opened and Jose Valim responded: Pipe in a list within a map not being encoded correctly? · Issue #633 · elixir-ecto/postgrex · GitHub