How to replace JSON with TOON?

Hi, I’m looking for a way to replace JSON in Phoenix (LiveView & Channel) with TOON to save resources and get faster parsing. Has anyone tried something similar or have any suggestions?

Someone really looked at JSON and said ‘you know what this needs? To be more like YAML because everyone loves YAML’?

4 Likes

The serialization of channels is configurable ootb with negotiation on connection. Feel free to add to the existing v1 and v2, both of which are JSON based. For browser/JS clients I’d wonder though if that’s really going to speed up things given how much of the js world is json.

2 Likes

It won’t change anything. The most important thing is how to ship strings to the browser as fast as possible. I don’t think any format change can beat the browser in parsing strings and modifying the DOM.

Ah, just looked at toon. I truely doubt it doing much at least for what the channel serialization or the lv contents transported on it is concerned. They’re already using no/short keys and efficient structures and on top of that stuff will most likely be compressed in transit. Unlike LLMs the browser doesn’t care nearly as much about a bit of duplication after decompression.

2 Likes

Currently, I use Phoenix Channel for communication between mobile and the backend. In some workloads, I noticed that parsing JSON is quite a heavy task. I replaced Jason with the native JSON library.

After looking at TOON, I found another interesting benefit: it can save bandwidth and reduce parsing time on both sides (mobile and backend).

1 Like

I think I will try it with Phoenix Channel first. LiveView might require too many changes.

Make sure that you’re comparing the GZipped sizes in your bandwidth estimate. People tend to forget to do this.

5 Likes

And while he’s at it, he should compare the Brotli compressed payload sizes as well. Many CDNs and modern browsers support that as well.

4 Likes

Is it more efficient than MessagePack? There are already Elixir libraries for that.

MessagePack is more efficient than TOON, but TOON is easier to integrate with the LLM.

Cool. How is an LLM used in this situation? Aren’t we talking about serialisation?

Yes, I’m thinking about TOON not only for saving resources, but also for integrating directly with LLMs to process a new type of API.

Concept:

Support voice commands and expose them through my current APIs (based on Phoenix Channel). The client will convert voice to text and send it to the server. On the server side, I will use an LLM to process the text like a normal API request.

I also plan to develop a new engine that processes business logic using an LLM (similar to an AI agent) instead of traditional code.

A little more about my current system: I’m building a low-latency system based on Phoenix Channel. One part of it is PhoenixGenApi, which I have published. After workload testing, I found that JSON consumes more resources than I expected (I already replaced Jason with the native Erlang JSON implementation).

I’m not sure if TOON is suitable for your case and I do not see me capable to judge this. I have worked with TOON to return smaller object based information to LLMs that saved some tokens over time and also changed a bit the operation style of the LLM.

I’ve used this: GitHub - kentaro/toon_ex: TOON (Token-Oriented Object Notation) encoder/decoder for Elixir - Optimized for LLM token efficiency · GitHub

and updated the TOON standard to the latest version in a fork: GitHub - xu-chris/toon_ex: TOON (Token-Oriented Object Notation) encoder/decoder for Elixir - Optimized for LLM token efficiency · GitHub

It can be used very similar like Jason by using @derive and feels like JSON therefore.

I believe, authors of TOML did, but they preferred INI over YAML.

Thanks for sharing. I checked the documentation and it looks like it won’t take much time for me to integrate this library.

I have a small question: Is there an option to decode keys into existing atoms?

I tried integrating with Phoenix Channel today.
Since Toon is compatible with JSON, I just replaced the json_parser option in Phoenix and on the client.

However, I found a small issue in the toon_ex library:

data = [1, 5, 3, "a", %{}] |> Toon.encode!()
"[5]:\n - 1\n - 5\n - 3\n - a" # missing the empty object as the last item

data |> Toon.decode!()
[1, 5, 3, "a"]

This issue will cause errors when decoding with Toon.decode in server side (by Phoenix serializer).

I’ll fix this in toon_ex lib and test it in a simple app before moving to a larger app with more complex objects.

This YAML reminds me of my experience with Python—one tiny whitespace issue once cost me an entire day of troubleshooting :sweat_smile:

Thank you all for your support.

Based on the suggested library from @xu-chris, I created a PoC using TOON with Phoenix Channels.

My approach:

  1. Updated the toon_ex library by adding a missing function so Phoenix can encode terms to iodata, and fixed some bugs.
  2. Updated the Phoenix config:
# Use Jason for JSON parsing in Phoenix
# config :phoenix, :json_library, Jason
config :phoenix, :json_library, ToonApp.MyToon
  1. Created a simple client in Elixir to verify it. I used the phoenix_client library.

Updated toon_ex repo. My PoC