clojure

Pavel Filipenco 2025-12-11T19:47:09.412949Z

When searching for "edn instead of json for web apps" I only find edn to json converters, no articles with people's experiences doing such a thing. So I'll ask here, anybody used EDN instead of JSON for APIs? If the frontend is also in clojure, then why not?

Joe R. Smith 2025-12-14T21:08:40.068759Z

+1 transit. It is edn for the wire.

jeaye 2025-12-15T06:28:49.150509Z

I've started with EDN, in the past, then tried transit when EDN became a performance issue. Transit was not compelling, perf-wise, compared to just JSON. I ended up expanding on the excellent jsonista library to add support for "tagged" JSON, which supports keywords, sets, and so on. This is significantly faster than both EDN and Transit.

👍 1
jeaye 2025-12-15T06:28:54.897569Z

The docs are here: https://github.com/metosin/jsonista?tab=readme-ov-file#tagged-json

jeaye 2025-12-15T06:33:08.620359Z

Just dug up the PR. Looks like the perf wins over Transit were 40-90%: https://github.com/metosin/jsonista/pull/36 Maybe interesting for others currently using Transit. 🙂

borkdude 2025-12-11T19:56:11.102309Z

It's pretty common to do this. If performance is an issue transit may also be worth trying

2025-12-11T19:58:16.429569Z

We did this at my last job but I didn't set it up so it mostly "just worked"

❤️ 1
2025-12-11T19:58:37.428449Z

Well to be more specific we used transit

2025-12-11T23:52:38.902849Z

When Transit came out, one of the motivations was that web browsers parsed JSON so fast that parsing Transit-JSON to a js/Object and then translating the Object to data structures with Transit was faster than JavaScript could parse EDN.

jussi 2025-12-12T11:10:52.358469Z

This was a good overall glance on "edn as json" imo https://nitor.com/fi/artikkelit/pitfalls-and-bumps-clojures-extensible-data-notation-edn

👍 1
❤️ 2
Ludger Solbach 2025-12-12T14:45:14.202269Z

EDN shines for human written data, not so much for machine written data. I would look into Transit for an API format.

👍 1
flowthing 2025-12-12T20:05:38.354319Z

> EDN shines for human written data, not so much for machine written data. I don't know that I agree with this. There's nothing that makes EDN worse than JSON for machines to read or write. EDN is often actually slightly smaller than the corresponding JSON (no commas, one fewer character for every key if using keyword keys rather than string keys (`:` vs ""), etc. It's just that JSON parsers tend to be insanely optimized, whereas EDN parsers don't (apart from https://github.com/tonsky/fast-edn/, I think).

flowthing 2025-12-12T20:06:43.919279Z

Except that yeah, there's no clojure.edn/write, which is a shame.

Ludger Solbach 2025-12-12T22:59:52.725789Z

generating (re-)readable EDN programatically is far from easy. Printing has to many side effects.

👍 1
2025-12-15T09:55:59.198979Z

? Isn't jsonista a JVM library?

👉 1
jussi 2025-12-15T10:03:57.052489Z

From Jsonista github-page > • Uses https://github.com/FasterXML/jackson-databind > • Mostly written in Java for speed But it is very good and fast json-library for Clojure.

István Karaszi 2025-12-11T21:22:18.444799Z

Cognitect test-runner error

István Karaszi 2025-12-11T21:22:39.034609Z

We have this error now and then when the Cognitect test-runner fails with a strange error.

István Karaszi 2025-12-11T21:23:03.639679Z

Running tests in #{"test"}
Execution error at cognitect.test-runner/restore-vars! (test_runner.clj:50).
No namespace: manta.action-handlers-test found
make: *** [Makefile:114: test] Error 1

István Karaszi 2025-12-11T21:23:46.076529Z

The namespace differs it is quite random, and it does exist. A simple-rerun usually solves the problem, so I have a hunch that this is a race condition or something simiar.

István Karaszi 2025-12-11T21:23:52.220609Z

Did anybody experience anything like that?

2025-12-11T21:24:08.196539Z

how are you running the tests? i see Make there

István Karaszi 2025-12-11T21:24:25.031479Z

test:
	rep '(rrun "cognitect.test-runner.api/test" {})'

István Karaszi 2025-12-11T21:26:17.157689Z

It is a project using deps.edn and we are using:

io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}

p-himik 2025-12-11T21:27:38.200419Z

What's rep? The only thing I can find is Sawfish, and surely it's not that. And what's rrun?

István Karaszi 2025-12-11T21:28:31.849489Z

That is a convenient function of ours:

(defn rrun
  [var-str & args]
  (apply (rr var-str) args))

István Karaszi 2025-12-11T21:28:42.289179Z

and rr is:

(defn rr
  [var-str]
  (requiring-resolve (symbol var-str)))

p-himik 2025-12-11T21:30:24.667879Z

Still not clear what rep is. But, approaching it from the other side - does it ever fail if you run the tests manually, the way the test runner documents the process?

István Karaszi 2025-12-11T21:30:51.691449Z

rep is this: https://github.com/eraserhd/rep

István Karaszi 2025-12-11T21:32:41.554929Z

Our setup is quite complicated, because we spin up the same Clojure process to run the unit test that we use later for behavior tests and browser tests as well

p-himik 2025-12-11T21:33:06.079899Z

Probably not related. One potentially pertinent fact - the No namespace: manta.action-handlers-test found error comes from calling (ns-publics ...). And it throws that error not when the namespace could not be loaded because none of the relevant files exist, but when the namespace was not required. So maybe you have some conditional requires. Maybe some dynamic requires. Maybe via some library like e.g. Integrant.

István Karaszi 2025-12-11T21:34:01.230289Z

We are also using integrant, yes

p-himik 2025-12-11T21:34:25.613429Z

> Our setup is quite complicated, because we spin up the same Clojure process to run the unit test that we use later for behavior tests and browser tests as well Nothing described makes it sound complicated. But it does smell a bit, to be honest. Could be that some tests implicitly depend on other tests. And you get that race condition because e.g. in 99% of the cases some namespace gets loaded in parallel testing but in the remaining 1% the loading order ends up being different.

p-himik 2025-12-11T21:35:39.030629Z

That error comes from a particular test or a set of tests, probably. Find which one, and you'll probably find the culprit.

István Karaszi 2025-12-11T21:38:06.809159Z

The problem is that the error message does not help since it hides the root cause

István Karaszi 2025-12-11T21:38:46.665149Z

> Nothing described makes it sound complicated. I did not describe the whole thing, just the parts felt relevant to the problem

p-himik 2025-12-11T21:40:30.402369Z

There should be a full stack trace somewhere. If there isn't, your setup is hiding it - not Clojure itself. Clojure's built-in REPL might redirect it to a file, but it also says so when it does that.

István Karaszi 2025-12-11T21:43:29.792279Z

I cannot find any stack trace in the main process either

István Karaszi 2025-12-11T21:44:06.412329Z

I am not blaming Clojure here, but I suspect that the test-runner has some strange issue

2025-12-11T21:45:01.866609Z

the test runner does some odd stuff. it gathers all test vars, updates the metadata of the vars to not have the tests anymore, runs the gathered tests, and then resets the metadata back to its original state

István Karaszi 2025-12-11T21:59:09.179909Z

That might be related to the problem we can see here

seancorfield 2025-12-11T22:45:35.405859Z

requiring-resolve is not entirely thread-safe, and ISTR test-runner does dynamic require as well (as your own code), so this def. sounds like a race condition around those dynamic requires...

seancorfield 2025-12-11T22:47:51.208139Z

And rep is connecting to an existing, running REPL, and executing code in that context so that has existing state -- which is likely also part of this problem.

seancorfield 2025-12-11T22:48:47.203809Z

(see https://ask.clojure.org/index.php/12346/potential-race-condition-in-requiring-resolve for more deets)