Absinthe scalar parse function never called

Hi,

I’m using postgreSQL’ JSONB object so store dynamic stats that can have any form given by the user.
Trying to use graphQL with absinthe, i’m currently having a problem.

See that stats is a list of :json :

  object :character do
    field(:id, :id)
    field(:stats, list_of(:json))
    field(:uuid, :string)
    field(:name, :string)
    field(:user, :user, resolve: assoc(:user))
    field(:items, list_of(:item), resolve: assoc(:item))
  end

  scalar :json do
    parse(fn input ->
      case Poison.decode(input.value) do
        {:ok, result} -> {:ok, result}
        _ -> :error
      end
    end)

    serialize(&Poison.encode!/1)
  end

For the request

query {
  charactersByUser(userId: 4) {
    name
    stats
    items {
      name
    }
  } 
}

The server currently returns

{
  "data": {
    "charactersByUser": [
      {
        "stats": [
          "{\"value\":13,\"name\":\"strengh\"}",
          "{\"value\":5,\"name\":\"Fierce\"}"
        ],
        "name": "Cramberry",
        "items": null
      },
      {
        "stats": [
          "{\"value\":0,\"name\":\"strengh\"}",
          "{\"value\":0,\"name\":\"*** size\"}"
        ],
        "name": "Le petit *** de Mikail",
        "items": null
      }
    ]
  }
}

You can see that my json “stats” is not parsed.
Ive also tried to add

      raise "not relevant"
      IO.puts("[BAAAAAAAAAAAAAAAAAAH] input.value")

Inside the parse function just to see if the app reacts… no effect

Any help appreciated… :frowning:

Since you’re returning json to the client the serialize/1 function is being called, if you were receiving the json field from client then the parse/1 function would be called.

Your schema has: field(:stats, list_of(:json)) and the client is currently receiving:

"stats": [
          "{\"value\":13,\"name\":\"strengh\"}",
          "{\"value\":5,\"name\":\"Fierce\"}"
        ],

Which is exactly correct (per your schema), since it is a list of JSON values (remember that JSON is actually a large string).

If you instead want to return a JSON object at the stats value then per GraphQL you need to provide it in the query. So instead of a query like:

query {
  charactersByUser(userId: 4) {
    name
    stats
  } 
}

You need to use:

query {
  charactersByUser(userId: 4) {
    name
    stats {
      value
      name
    }
  } 
}

This is because the whole point of GraphQL is for the client to explicitly request each field that it wants to receive, all the way down to each field.

1 Like

Oh ok now i feel dumb lol

Thank you, i didn’t thought that way… it was late

Thanks ^^

1 Like