LuchoTurtle

LuchoTurtle

I’ve researched for a while but I can’t seem to get this to work properly and it’s been a frustrating experience, as everything I do keeps getting me this error.

I have the following schema:

  @derive {Jason.Encoder, except: [:__meta__, :__struct__, :timer, :inserted_at, :updated_at]}
  schema "items" do
    field :person_id, :integer
    field :status, :integer
    field :text, :string

    has_many :timer, Timer
    many_to_many(:tags, Tag, join_through: ItemTag, on_replace: :delete)

    timestamps()
  end

I’m using the @derive annotation to properly decode so I can return the item to the user.
I have this simple function that preloads the tags associated to an item accordingly.

  def get_item(id, preload_tags \\ false ) do
    item = Item
    |> Repo.get(id)

    if(preload_tags == true) do
      item |> Repo.preload(tags: from(t in Tag, order_by: t.text))
    else
      item
    end
  end

The problem is that, in the API controller…

          # `item` is the object returned from `get_item`. Assume an `item` is found.
          item ->
            if retrieve_tags do
              json(conn, item)
            else
              item = Map.drop(item, [:tags, :timer])
              json(conn, item)
            end

if I try to return an item without tags (else statement), I keep getting the same error.

no function clause matching in Jason.Encoder.App.Item."-inlined-encode/2-"/2

If I try to to not drop the :tags property, I get the oh-so familiar error of Jason.Encoder not being able to encode the association.

** (RuntimeError) cannot encode association :tags from App.Item to JSON because the association was not loaded.

You can either preload the association:

    Repo.preload(App.Item, :tags)

Or choose to not encode the association when converting the struct to JSON by explicitly listing the JSON fields in your schema:

    defmodule App.Item do
      # ...

      @derive {Jason.Encoder, only: [:name, :title, ...]}

I want to be able to just return the item without tags if the user doesn’t want to. Returning with tags works fine, it’s just that the without tags always errors out with the aforementioned error.

Is my @derive annotation wrong? It’s the only way I found to serialize tags property either if it exists or doesn’t.

Thank you very much and I hope you have a wonderful day!

Showing Posts 1 to 4

LuchoTurtle

LuchoTurtle OP

An update on this:

Apparently, if I remove the :__struct__ field, it works.

          item ->
            if retrieve_tags do
              json(conn, item)
            else
              item = Map.drop(item, [:tags, :__struct__])
              json(conn, item)
            end

This is weird, because Jason.Encoder’s documentation explicitly says:

By default all keys except the :__struct__ key are encoded.

Perhaps I’m going about this the wrong way :thinking:

whatyouhide

whatyouhide

Elixir Core Team

There’s a chance that when you specify keys to not encode with :except, the default gets overridden? I’m not super familiar with Jason internals. In either case, I’d recommend opening an issue in the repo, at the very least I bet the error message could be improved :wink:

dimitarvp

dimitarvp

I would try removing the special fields from the derive line. No need to be clever, this should be handled for you automatically.

LuchoTurtle

LuchoTurtle OP

Thanks for the answer, guys!

The reason this stopped working in the else statement of

          item ->
            if retrieve_tags do
              json(conn, item)
            else
              item = Map.drop(item, [:tags, :__struct__])
              json(conn, item)
            end

is because when I use Map.drop/2 to remove the keys, the item is no longer a struct. Jason.Encode only works on structs of the specified Item schema, hence why it fails.

I understand why it fails but it’s a wee annoying that there’s no simple way of “bypassing” or doing a custom implementation whenever a field has an Ecto.NotLoaded value.

Basically..

item #=> %App.Item{
  __meta__: #Ecto.Schema.Metadata<:loaded, "items">,
  id: 1,
  person_id: 0,
  status: 2,
  text: "random text",
  timer: #Ecto.Association.NotLoaded<association :timer is not loaded>,
  tags: #Ecto.Association.NotLoaded<association :tags is not loaded>,
  inserted_at: ~N[2023-01-26 17:05:45],
  updated_at: ~N[2023-01-26 17:05:45]
}

it fails in tags fields because @derive {Jason.Encoder, except: [:timer, :inserted_at, :updated_at]} doesn’t know what to do with the Ecto.Association.NotLoaded value.

Thanks for the response though, guys! Thoroughly appreciated!

— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews