How to set :json_library into ecto config

Hi,

Assuming the following schema:

# user.ex
defmodule Schema.User do
  @moduledoc false
  use Ecto.Schema
  import Ecto.Changeset

  @required_params [:email, :password]
  @optional_fields []

  schema "users" do
    has_many :orders, Schema.Order
    embeds_one :profile, Schema.User.Profile

    field :email, :string
    field :password, :string, virtual: true
    field :encrypted_password, :string
    timestamps()
  end

  def changeset(user,  params \\ %{}) do
    user
    |> cast(params, @required_params ++ @optional_fields)
    |> validate_required(@required_params)
    |> unique_constraint(:email, name: :unique_email)
    |> validate_format(:email, ~r/\S+@\S+\.\S+/)
    |> validate_length(:password, min: 6)
  end
end
# user/profile.ex
defmodule Schema.User.Profile do
  @moduledoc false
  use Ecto.Schema
  import Ecto.Changeset

  @required_params [:first_name, :last_name, :gender, :phone]
  @optional_fields [:image]

  embedded_schema do
    field :first_name, :string
    field :last_name, :string
    field :gender, :string
    field :phone, :string
    field :image, :string
  end

  def changeset(profile,  params \\ %{}) do
    profile
    |> cast(params, @required_params ++ @optional_fields)
    |> validate_required(@required_params)
  end
end
# config.exs
use Mix.Config

config :persistence, Persistence.Repo,
    adapter: Ecto.Adapters.MySQL,
    database: "antidote",
    username: "root",
    password: System.get_env("DATABASE_PASSWORD"),
    hostname: "localhost",
    port: "3306"
iex >u = Schema.User.changeset(%Schema.User{}, %{:email => "contact@alexandrubagu.info", :password => "my_password"})
iex> p = Schema.User.Profile.changeset(%Schema.User.Profile{}, %{:first_name => "first", :last_name => "last_name", :gender => "m", :phone => "+40"})
iex >u = Ecto.Changeset.put_embed(u, :profile, p)
iex> Persistence.Repo.insert(u)
** (ArgumentError) application :ecto is not loaded, or the configuration parameter :json_library is not set
           (elixir) lib/application.ex:261: Application.fetch_env!/2
                    lib/ecto/adapters/mysql/connection.ex:47: anonymous fn/1 in Ecto.Adapters.MySQL.Connection.map_params/1
           (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
           (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
                    lib/ecto/adapters/mysql/connection.ex:32: Ecto.Adapters.MySQL.Connection.execute/4
                    lib/ecto/adapters/sql.ex:235: Ecto.Adapters.SQL.sql_call/6
                    lib/ecto/adapters/mysql.ex:178: Ecto.Adapters.MySQL.insert/5
                    lib/ecto/repo/schema.ex:397: Ecto.Repo.Schema.apply/4
....

Because I use :map struct in MySQL, ecto it requires to define :json_library but I didn’t find the documentation for this.
Another solution is to define a custom type as it follows:

defmodule App.Types.JSON do
  @behaviour Ecto.Type

  def type, do: :json

  def cast(any), do: {:ok, any}
  def load(value), do: Poison.decode(value)
  def dump(value), do: Poison.encode(value)
end

So, I want to know where/how can I define the :json_library if anyone knows :slight_smile:
Thanks :smiley:

1 Like

Which Ecto version are you using? In Ecto 2.0 there are some docs at https://hexdocs.pm/ecto/2.0.0/Ecto.Schema.html, search for “json_library”

Also, make sure that both ecto and poison are in your application list in mix.exs

2 Likes

I’m using ecto ~> 2.0.6. Thanks, I’ve missed that :slight_smile: