0

I need to put some JSON-LD content inside a script tag. Today, I’m put the content like this:

page_live.ex

defmodule ProjectWeb.PageLive do
  use ProjectWeb, :live_view

  @data_structure %{
    "@context": "http://www.schema.org",
    "@type": "WebSite",
    name: "Project",
    url: "https://project.com/"
  }

@impl true
  def mount(_params, _session, socket) do
    socket = assign(socket, data_structure: @data_structure)

    {:ok, socket}
  end
end

root.html.leex

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
...
<%= if @data_structure do %>
  <script type='application/ld+json'>
    <%= Poison.encode!(@data_structure) %>
  </script>
<% end %>
...
</head>
<body>
<%= @inner_content %>
</body>
<html>

The Poison lib always convert to String. I need a JSON.

How can I put the JSON content inside the script tag?

Allan Duarte
  • 157
  • 1
  • 3
  • 14
  • What exactly does `Poison.encode!/1` return for you? It should return a string, but it should be a string representation of a JSON object. – Everett Sep 14 '21 at 12:31
  • @Everett yes, it is the return is a string representation of a JSON but I need a JSON. – Allan Duarte Sep 14 '21 at 13:21
  • Can you elaborate what you mean by "a JSON"? I'm not familiar with that terminology. – Everett Sep 14 '21 at 14:00
  • Do you perhaps mean that you need the data bound to a JS variable? Like `var x = <%= Poison.encode!(@data_structure) %>;` ? – Everett Sep 14 '21 at 15:18
  • I need to return {@context: "http://schema.org", @type: "WebSite"} and not "{\"@type\":\"WebSite\",\"@context\":\"http://www.schema.org\"}" – Allan Duarte Sep 14 '21 at 16:06
  • Perhaps https://hexdocs.pm/phoenix_html/Phoenix.HTML.html#javascript_escape/1 might be useful? – Everett Sep 14 '21 at 17:54
  • I haven't tried it yet but it looks like I'll need to create a view to render the tag content. – Allan Duarte Sep 15 '21 at 13:25

1 Answers1

0

The trick is to use the raw function to mark the encoded string as "safe" for use as JSON.

Assuming your controller is passing a map value to your view via something like:

def index(conn, _params) do
  render(conn, "index.html", foo: %{x: "xray", y: "yep"})
end

Then you can do something like this (should be the same using Poison):

<script>
  var x = <%= @foo |> Jason.encode!() |> raw() %>;
  console.log(x);
</script>
Everett
  • 8,746
  • 5
  • 35
  • 49