explanation
- (a) Why making a JSON parser?
- I think that Zig's std.json parser fucking sucks
- I write a ton of web apps, therefore, I need a JSON parser
- idk
- (a) What's wrong with std.json?
- It is impossible to override the defaults, I'll proceed to tell you the defauls
- It parses
enums
intostrings
instead ofints
Packed structs
get parsed as structs, instead ofints
max_value_len
, couldn't they just learn how to resize a buffer? Is it so difficult?- Strings are not dupped, you have to MANUALLY enable this
- They don't support parsing unions, laughable
- It crashes randomly when the type doesn't strictly match the payload
error.MissingField
, you have to annotate every 'optional' field with= null
, do they don't know how JSON works?- Considering what I've said so far, the type reflection is just awful, and there is no way to parse without reflection, just straigt up data? Or is there?
- Huge boilerplate to define custom parsing, if every default is overriden then the only option left is to define your own
jsonParse
function, which generates huge boilerplate - Like 10 different functions for doing the exact same thing, parsing,
innerParse
,innerParseFromValue
,parseFromSlice
,parseFromSliceLeaky
,parseFromTokenSource
,parseFromTokenSourceLeaky
(wtf?),parseFromValue
,parseFromValueLeaky
- The debug options are trash, you have to quite literally pass a struct called
Diagnostcs
- This article
- (a) Is this better than std.json?
- I don't know, I just know that it parses JSON and it works, it's simple, the code is readable and straightforward, it is 3 simple files that do simple things, nothing else
- This parser is based off of a string pool written by Andrew Kelley, so it must be good, watch a video
- Probably no, but less featureful software (or less worse) is usually better than over-engineered mess
- (a) Ok but all of your reasons are dumb
- I'll answer this later
Behaviour
- All control characters except DEL are forbidden
- Null control characters, eg: U+0000 are forbidden and will be ignored by the parser
- Of course, uses null terminated strings, clearly this is not the best approach, but it's memory efficient and fast as fuck!
- It passes most unit tests of the JSON test suite, totalling 570 tests as of 2025-05-29 when I'm writing this.
- All defaults are configurable via the
Flags
bitfield - Reflection is supported
Sic respondeo:
The Zig Discord server is plagued with modern scum, of course, modern scum will dismiss all of my claims or label them as "dumb" or "you're using it wrong!", has any of these individuals not considered that Zig is over complicated? There is a reason why Andrew Kelley himself detached from the communities and has spoken in multiple instances about the "shitification" of software communities, it's like turning a good community of like-minded programmers into a soydev shill. One good thing that he did was shutting down the r/zig subreddit. On different note, I defend simplicity and minimalism, so I am not saying that every Zig developer who thinks differently is scum, I just say that if you cannot think beyond your viewpoint you will reach nowhere. Lastly, if your software is not straightforward and simple to use, then why criticising someone for now knowing how to use it? The only reasonable way to make software complicated is as long as user friendliness is not a tradeoff for performance or minimalism.
benchmark for the nerds
first benchmark is 2 runs and aether is allocating twice, for storing data, and for displaying data in hashmaps and array lists
Benchmark | Runs | Total Time | Time/Run (Avg ± σ) | Range (Min ... Max) | p75 | p99 | p995 |
---|---|---|---|---|---|---|---|
aether | 2 | 1m14.271s | 37.135s ± 960.345ms | (36.456s ... 37.814s) | 37.814s | 37.814s | 37.814s |
aether [MEMORY] | 54.095MiB ± 0B | (54.095MiB ... 54.095MiB) | 54.095MiB | 54.095MiB | 54.095MiB | ||
std.json | 2 | 1m12.731s | 36.365s ± 621.288ms | (35.926s ... 36.805s) | 36.805s | 36.805s | 36.805s |
std.json [MEMORY] | 43.420MiB ± 0B | (43.420MiB ... 43.420MiB) | 43.420MiB | 43.420MiB | 43.420MiB |
this is 1 run of the code located in benchmarks/main.zig
, as you can see aether is drastically more efficient
Benchmark | Runs | Total Time | Time/Run (avg ± σ) | (min ... max) | p75 | p99 | p995 |
---|---|---|---|---|---|---|---|
aether | 1 | 29.435s | 29.435s ± 0ns | (29.435s ... 29.435s) | 29.435s | 29.435s | 29.435s |
aether [MEMORY] | 42.393MiB ± 0B | (42.393MiB ... 42.393MiB) | 42.393MiB | 42.393MiB | 42.393MiB | ||
std.json | 1 | 34.889s | 34.889s ± 0ns | (34.889s ... 34.889s) | 34.889s | 34.889s | 34.889s |
std.json [MEMORY] | 43.420MiB ± 0B | (43.420MiB ... 43.420MiB) | 43.420MiB | 43.420MiB | 43.420MiB |
memory wise, aether is not much bigger, it's basically equal to std.json I presume that the time that aether takes running is because of SIMD, but I can't be sure