HipJSON: A high performance implementation of JSON parser with std.json syntax. Used by Redub and Hipreme Engine
Hipreme
msnmancini at hotmail.com
Sat Nov 1 03:43:02 UTC 2025
On Thursday, 30 October 2025 at 16:40:54 UTC, Dennis wrote:
> On Thursday, 30 October 2025 at 13:02:16 UTC, Hipreme wrote:
>> Redub uses a cache system in which the hash of an object
>> becomes a key. This does not translate well to structs as they
>> are "random" keys. (...)
>
> So you have several use cases where the keys are not a small
> set known ahead of time, but constructed dynamically. Makes
> sense, though now I wonder why you would use JSON for your
> cache or filesystem when performance is such a concern. Or when
> it's not a concern, why std.json doesn't suffice.
>
>> There is another case in which the dynamic type API is kinda
>> important, which is mostly when you do union types, so one
>> would still need a good representation of it:
>
> You could define:
>
> ```D
> struct Input
> {
> string keyboard;
> string gamepad;
> string analog;
> string axis;
> }
> ```
>
> And then check the length of those strings to see if they have
> a value.
>
> Either way, it's still useful to have a fast JSON parser using
> dynamic objects, and using std.json's API makes it an easy
> upgrade.
The reasons for why std.json didn't suffice:
- It uses a bunch of phobos dependencies which I can't use since
I target multiple platforms with Hipreme Engine
- Redub started using hipjson because I found out that it was
going way faster than std.json even though that meant I would use
std.conv.to or other phobos functions
- I made that project available because I found out it was the
fastest implementation for dynamic JSON objects in D
- After that, I grew a little nerdy on that and then made up
d-segmmented-hashmap which was my response in going even further
Right now, HipJSON just release v1.0.1 which also supports
streaming API:
```d
import hip.data.json;
import std.exception;
JSONValue myJson;
JSONParseState state = JSONParseState.initialize(0);
enforce(JSONValue.parseStream(myJson, state, `{`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `h`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `e`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `o`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `:`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, ` `) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `w`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `o`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `r`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `d`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) ==
JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `}`) !=
JSONValue.IncompleteStream);
import std.stdio;
writeln(myJson); //{"hello" : "world"}
```
What was more of a POC also wasn't that hard to get done, though
I've got some bugfixes and even more performance improvement
More information about the Digitalmars-d-announce
mailing list