Skip to content

Conversation

elfenlaid
Copy link
Contributor

Address #6461

The changes set the built-in JSON library as a default JSON library.

The idea is to check whether the built-in JSON library is present and use it if so:

  @default_json_library if Code.ensure_loaded?(JSON), do: JSON, else: Jason

  def json_library do
    Application.get_env(:phoenix, :json_library, @default_json_library)
  end

Correct me if I'm wrong, but I think a naive check of whether the library is present during compilation time should work, as it's a built-in library.


What I'm not sure about is whether such a move results in a breaking change.

It could be a breaking change for projects that don't specify the json_library and use @derive Jason.Encoder on structures passed to Phoenix.Controller.json/2. That sounds pretty niche, especially given that the template project includes:

config :phoenix, :json_library, Jason

Also, I'm specifically leaving the jason dependency in place for pre-27 OTP versions.


Please let me know what you think and whether the changes make sense. In other words, maybe it would be better to stick with Jason until Phoenix requires OTP 28.


Similar discussions / changes:

Use Jason instead of Poison for json encoding by chrismccord #2734phoenixframework/phoenix
Investigate using Jason instead of Poison #2693phoenixframework/phoenix

Use JSON instead of Jason by kubosuke #234felt/geo

Now [`/hello/Frank`] in your browser should display `From messenger Frank` as plain text without any HTML.

A step beyond this is rendering pure JSON with the [`json/2`] function. We need to pass it something that the [Jason library](`Jason`) can decode into JSON, such as a map. (Jason is one of Phoenix's dependencies.)
A step beyond this is rendering pure JSON with the [`json/2`] function. We need to pass it something that the [JSON library](https://hexdocs.pm/elixir/JSON.html) can decode into JSON, such as a map.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's how it looks like with mouse hover:

Image

format: "\n$time $metadata[$level] $message\n"

config :phoenix,
json_library: Jason,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably here we would need to have something similar to if Code.ensure_loaded?(JSON), do: JSON, else: Jason if that conditional loading trick makes sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does and yes, we definitely need it (and also adjust the tests to assert the correct errors in CI)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, for sure. I wasn't certain if the said approach (determining JSON availability by Code.ensure_loaded?) is the correct one. But if it will do, then yes, I'll update the tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can wait for José to chime in. Sometimes you need Code.ensure_compiled, but I think for a built in module ensure_loaded should be fine?

@SteffenDE SteffenDE requested a review from josevalim September 23, 2025 08:56
lib/phoenix.ex Outdated
"""
def json_library do
Application.get_env(:phoenix, :json_library, Jason)
Application.get_env(:phoenix, :json_library, @default_json_library)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot change the default here, as that would be a breaking change. We can only change it in new apps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. It makes things a bit simpler for this PR:

  • Mark the default library in Phoenix.json_library as a breaking change for Phoenix v2.0
  • Use JSON for new apps
  • Make sure that tests pass with both JSON and Jason libraries

What I'm not sure is whether changes in config/config.exs are safe?

I could be wrong, but it seems that they aren't propagated to library users. The users will only see variables from application.env, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing config is safe!

end

assert_raise json_error,
~r/invalid byte 111 at position \(byte offset\) 0|unexpected byte at position 0: 0x6F \("o"\)/, fn ->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not the most elegant solution, but...

Image

@elfenlaid elfenlaid requested a review from SteffenDE September 23, 2025 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants