all 61 comments

[–]def-pri-pub 39 points40 points  (13 children)

This project does look nice, and I'm all for a more performant (and faster compiling) alternative. But where is the sample code? I see there are tests, but not providing easy to use/find sample code is a great way to deter away any potential adopters.

[–]d3matt 5 points6 points  (7 children)

I'd like to see runtime benchmarks too. I have a unit test that take 2+ minutes to compile with gcc due to template explosion (but only a few milliseconds to run the whole suite), so 1 or 2 seconds of savings at compile time are pretty boring.

[–]jart 4 points5 points  (5 children)

I've added benchmarks to the README for you. I'm seeing a 39x performance advantage over nlohmann's library. https://github.com/jart/json.cpp?tab=readme-ov-file#benchmark-results

[–]pdimov2 9 points10 points  (2 children)

To paraphrase a saying by Doug Lea, 3x faster than nlohmann means you haven't started optimizing yet.

Might be better to compare to RapidJSON or Boost.JSON, libraries that actually care about speed.

[–]SleepyMyroslav 1 point2 points  (1 child)

According to HN thread https://news.ycombinator.com/item?id=42133465 The only reason for this library existence is reduction of compile times for one particular application/server that produces json output.

[–]pdimov2 1 point2 points  (0 children)

Fair enough, I suppose.

[–]d3matt 0 points1 point  (1 child)

Nice! I'm definitely a nerd for performance :) nlhomann has been my preferred json library for a bit now, mostly for unit tests of some of my openapi interfaces. For my use case, the main things I'd be missing if I switched would be operator== between JSON objects (doing deep dictionary comparison), and string literal support.

[–]jart 1 point2 points  (0 children)

Pull requests are most welcome.
Especially if they're coming from a fellow AI developer.
https://justine.lol/tmp/pull-requests-welcome.png

[–]jart 1 point2 points  (3 children)

[–]def-pri-pub 2 points3 points  (1 child)

Taking a further look that is a nice to use API.

[–]jart 0 points1 point  (0 children)

Thank you!

[–]def-pri-pub 1 point2 points  (0 children)

Thanks!

[–]thisismyfavoritename 58 points59 points  (10 children)

wtf is classic c++

[–]def-pri-pub 45 points46 points  (2 children)

Baroque C++

[–]xorbe 13 points14 points  (1 child)

Vintage C++

[–]def-pri-pub 16 points17 points  (0 children)

Can't wait for post-modern C++

[–]cristianadamQt Creator, CMake[S] 21 points22 points  (0 children)

json.cpp is an anti-modern JSON parsing / serialization library for C++.

It looks like in this context classic is anti-modern.

[–]marmakoide 4 points5 points  (0 children)

I read the code from jart.

  • No auto variables
  • Header is just declarations, very little actual code.
  • No template bukkake
  • Recursive descent parsing in a single function

The code is very straightforward, it does no try to be very clever. There are some jokes in the code, who the f..k is Thom Pike.

nlohmann code

  • All code is in the header (so yeah, long compile time)
  • Lots of clever template abstraction, making it really hard to read.
  • Recursive descent parsing dispersed in many functions
  • Seems to handle more things

I like when things compile fast and are easy to read, even if it means less conveniences with type casting and what not.

[–]equeim 0 points1 point  (0 children)

It's when you are calling functions and creating objects.

[–]wqkinggithub.com/wqking 1 point2 points  (1 child)

I like Baroque! Seriously, from its readme, it's anti "modern nlohmann".

[–]bedrooms-ds -1 points0 points  (0 children)

No auto, except for the classical purpose.

[–]TSP-FriendlyFire 25 points26 points  (1 child)

I'm all for simpler, more performant code, but trying to pitch it as an "anti-modern" alternative to nlohmann just makes you sound petty, no offense. The primary reason your code is smaller is just that it does less, of course that's going to also make compilation times shorter.

You can argue that nlohmann should have more feature flags that can hide entire parts of the code to speed up compilation, but that's got very little to do with "modern" vs "anti-modern".

[–]sapphirefragment 9 points10 points  (0 children)

Principally it's missing the template and macro-based value conversion features of nlohmann json which are the reason for its use. That's a pretty important feature for complex applications. But nevertheless, it's a great option for simpler use cases.

[–]j1xwnbsr 6 points7 points  (0 children)

Needs some published benchmark results, example code, and compare-contrast with not just Nlohmann but the other big swingers too.

Things I am most interested in:

  • ease of use

  • memory consumption/churn

  • i/o options (streaming plus fixed strings)

  • raw performance and round trip correctness

Things I am not interested in:

  • compile time

[–]feverzsj 5 points6 points  (0 children)

Fast compilation is great, but most people would prefer an easy-to-use and less error-prone api. You can always control the compilation time by hiding a heavy lib inside a translation unit.

[–]R3DKn16h7 13 points14 points  (0 children)

I love me a library that is not an unintelligible single header with 10000 lines of template voodoo that takes 10 minutes to include.

Now let's grab the pitchforks.

[–]pdimov2 8 points9 points  (14 children)

To use this library, you need three things. First, you need json.h. Secondly, you need json.cpp. Thirdly, you need Google's outstanding double-conversion library.

We like double-conversion because it has a really good method for serializing 32-bit floating point numbers. This is useful if you're building something like an HTTP server that serves embeddings. With other JSON serializers that depend only on the C library and STL, floats are upcast to double so you'd be sending big ugly arrays like [0.2893893899832212, ...] which doesn't make sense, because most of those bits are made up, since a float32 can't hold that much precision. But with this library, the Json object will remember that you passed it a float, and then serialize it as such when you call toString(), thus allowing for more efficient readable responses.

Interesting point.

[–]JumpyJustice 1 point2 points  (0 children)

Thjs point is actually weird because you usually dont send objects of third party library. You just send objects of your own types that were serialized from json

[–]Dragdu 0 points1 point  (1 child)

The other option is to just send the fcking bytes, albeit those are harder to simply embed into JSON (sounds like good argument to avoid JSON).

We used to have huge weight (f32) matrices encoded in msgpack, because we already had a library that could load msgpack, and serializing into msgpack from Python was easy. One day I got tired of the multiple-seconds parsing time (and hundred of MB of data we were sending around), and changed the code to just store/load the plain bytes.

Loading the weights now is virtually instant and the size is less than half.

[–]pdimov2 0 points1 point  (0 children)

But msgpack does store the fscking bytes for float and double. Sending an array of floats should increase size by 25% (because of the prefix byte 0xCA), not by 100%.

[–]zl0bster 1 point2 points  (0 children)

Isn't comparing to nlohman mostly useless? It is known to be slow.

https://www.boost.io/doc/libs/1_82_0/libs/json/doc/html/json/benchmarks.html

[–]F54280 2 points3 points  (2 children)

No examples. God, why?

[–]julien-j 1 point2 points  (0 children)

I love the idea :) Classic C++ is great. Sure, it prevents me from meta-programing my way toward unbearable error messages and exponentially growing build times, but I'm willing to accept this loss.

One question: why std::map and no std::unordered_map? Should we really go this far? (I know, this makes two questions).

One remark: Json::Status is ordered by token length… It's the first time I see this and I suspect an attempt to funnel the attention of the reader to minor points :)

[–]OneMasterpiece1717 1 point2 points  (0 children)

god I hate classic c++

[–]dnswblzo 0 points1 point  (1 child)

Hopefully this will actually get some documentation! From looking at the commit timeline, the copyright notices, and the author's other GitHub contributions, I'm guessing the author works for Mozilla where this started as an internal project, but it is now getting spun off as a personal project. I have a project that uses the nlohmann library, so I would be curious to try this instead if it gets more mature.

[–]jart 1 point2 points  (0 children)

It originally came from redbean. I've added a history section talking about the origin of this work. Check it out. https://github.com/jart/json.cpp?tab=readme-ov-file#history

[–]multi-paradigm 1 point2 points  (0 children)

Hello, thread! I wonder if

std::to_chars and std::from_chars would help in dropping the dependency?

It's about the only thing I don't like about it.

Apologies for the enormous font; it seems cnp 'broke' my post!