Live data from Hacker News

JSON for Modern C++

github.com

111–120 of 125 posts

Re: JSON for Modern C++

#111
post #60
post #32

Earlier quoted context omitted.

Wikis on GitHub are themselves git repos and can be cloned separately: https://help.github.com/en/articles/adding-or-editing-wiki-p...

Yeah, but they have to be cloned separately. And not all projects have them. A doc directory gets you the same thing, easier.

Makes me wonder whether people have tried making the wiki repository a git submodule/subtree of the code repository.

Re: JSON for Modern C++

#113

Earlier quoted context omitted.

JSON is just a transport. Get the payload off from library structures to your own data structures ASAP, to remove dependencies, and to profit from your own setup. And how to make the transformation? Using your own setup. No point in expressing (duplicating!) your own data structure definitions in a random library's DDL (which, apart from the inflicted duplication, will not fit very well since it doesn't know your pro…

> Get the payload off from library structures to your own data structures ASAP, I don't understand, doing this step is exactly why you need to have a library such as the one which is being discussed here. There's no in-language way in C++ to go from a string that looks like `{ "foo": [1,2,3] }` to `struct { int foo[3]; }`.

IMO we should not have a multi-dozens-KLOC library for something that should be almost invisible. And I don't think that being invisible is the purpose of this library.

I would just specify your case as a data item:

    ARRAY_ITEM("foo", foo, INT, 3)
And that's really all, specification-wise. Here ARRAY_ITEM is a simple macro that calculates the offset of the array within the struct (need to give the struct a name!), so that results maybe in { .srcfield="foo", .typekind=TYPE_ARRAY, .arraylength=3, .basetype=INT, offset=offsetof(MyStruct, foo) } or something like that. One can compute the length of the C array at compile time and verify that the lengths match, so there will be absolutely no danger of making a wrong data item.

The corresponding code that handles the data items of kind ARRAY_ITEM would be something like this:

    case TYPE_ARRAY: {
        char *store = add_offset(&myStruct, spec->offset);
        int elemSize = typeKindToElementSize[spec->typekind];
        JsonArray *jsonArray = get_json_array(jsonObject, spec->srcfield);
        for (int i = 0; i arraylength; i++) {
            JsonValue *jsonValue = get_json_array_element(jsonArray, i);
            /* This makes sure the dynamic type of jsonValue matches, then
            does the appropriate conversion and stores the thing. We also
            want to check errors, either now or at the end. */
            store_json_value(jsonValue, spec->basetype, store + (i * elemSize));
        }
    }
You'll need I'm likely to write a new version of this for every new project, to avoid dependencies and to allow for change.

Re: JSON for Modern C++

#114

Earlier quoted context omitted.

> Get the payload off from library structures to your own data structures ASAP, I don't understand, doing this step is exactly why you need to have a library such as the one which is being discussed here. There's no in-language way in C++ to go from a string that looks like `{ "foo": [1,2,3] }` to `struct { int foo[3]; }`.

IMO we should not have a multi-dozens-KLOC library for something that should be almost invisible. And I don't think that being invisible is the purpose of this library. I would just specify your case as a data item: ARRAY_ITEM("foo", foo, INT, 3) And that's really all, specification-wise. Here ARRAY_ITEM is a simple macro that calculates the offset of the array within the struct (need to give the struct a name!), so…

well, that's a possibility but only works in the simplest case of C-like structs. What if I have this API instead :

    struct MyWidget {
        void setFoos(const std::vector& foos) { m_foos = foos; updateUI(); }
    };
or this :

    struct MyWidget {
        void addFooInstance(int);
    };
Also, ugh. macros. what happens if you talk to 5 different network protocols all with more-or-less-JSON-like semantics - do you now have ARRAY_ITEM_JSON, ARRAY_ITEM_BSON, ARRAY_ITEM_CBOR, ARRAY_ITEM_YAML ? What when the format changes so that `ARRAY_ITEM("foo", foo, INT, 3)` now wants floats ? woohoo, magic truncation instead of a compile error.

As they say : thanks but no thanks, I'll stay with `for (auto& [key, value] : o.items())` which ensures that everyone including the fresh-out-of-school student can understand what happens without needing to read obtuse macro definitions

Re: JSON for Modern C++

#115

Earlier quoted context omitted.

IMO we should not have a multi-dozens-KLOC library for something that should be almost invisible. And I don't think that being invisible is the purpose of this library. I would just specify your case as a data item: ARRAY_ITEM("foo", foo, INT, 3) And that's really all, specification-wise. Here ARRAY_ITEM is a simple macro that calculates the offset of the array within the struct (need to give the struct a name!), so…

well, that's a possibility but only works in the simplest case of C-like structs. What if I have this API instead : struct MyWidget { void setFoos(const std::vector & foos) { m_foos = foos; updateUI(); } }; or this : struct MyWidget { void addFooInstance(int); }; Also, ugh. macros. what happens if you talk to 5 different network protocols all with more-or-less-JSON-like semantics - do you now have ARRAY_ITEM_JSON, AR…

> What if I have this API instead

I say let data be data and write code where you need code. How does the library handle this in one step? How long does it take you to find out?

> Also, ugh. macros.

Data macros are the best. You don't have to debug them at runtime, they let you get rid of a lot of boilerplate such as compile-time computations (e.g. offsetof(), sizeof())

> do you now have ARRAY_ITEM_JSON, ARRAY_ITEM_BSON, ARRAY_ITEM_CBOR, ARRAY_ITEM_YAML

I'm really sorry if you have to do that. I never had, and likely never will. But I'd probably just write the example I gave, in 5 flavours, in 5 separate implementation files. The alternative, dealing with 5 oversized libraries that approach this thing in a totally different way, is not appealing to me at all.

> What when the format changes so that `ARRAY_ITEM("foo", foo, INT, 3)` now wants floats ? woohoo, magic truncation instead of a compile error.

No, runtime error message about a wrong type in a JSON payload. Or if you mean this: the type of the C array's elements changed from int to float. Then just check the type of the array elements against the specified type (INT) which should expect a specific C type. There are easy ways to get a representation of the array element type in C++ as well as an in C (the macro can do it automatically).

> obtuse macro definitions

#define ARRAY_ITEM(_srcfield, _arraylength, _basetype, _dstfield) { .srcfield=_srcfield, .typekind=TYPE_ARRAY, .arraylength=_arraylength, .basetype=_basetype, .offset=offsetof(MyStruct, _dstfield) }

If you think that is obtuse reconsider C++ templates.

Re: JSON for Modern C++

#116
post #102

Earlier quoted context omitted.

but in this context TOML and JSON are almost isomorphic (ok, parsing JSON is more unreliable than many realize apparently). As far as I can see the problem is that it is difficult to convert arbitrary JSON object to C++ objects. TOML (I also like it, for different reasons) isn't gonna help with that.

Wait, everyone is complaining you can't do `object.member.submember`? I don't see the issue with object['member']['sub']. It is slightly more typing, but such is life.

I do not know about everyone, but it I believe it is hard to convert a flexible JSON object into a C++ struct (or something with comparable performance), my understanding is that this library helps with that.

Re: JSON for Modern C++

#117
post #42

Earlier quoted context omitted.

Reflection isn't required; keys in JSON are strings, and there are basic data types that are supported (strings, numbers, booleans, arrays, and dictionaries which are more of the same). What's wrong with writing "initializers" which are serializers/deserializers? If you're looking for automatic file format to C++ class object, why settle for JSON (whether it's this library or JSONCpp) why not use Thrift or Protocol B…

>why settle for JSON Because I'm not writing code in a vacuum, and JSON is what everyone else is using. JSON is chosen for simplicity & interoperability.

This exactly, sometimes you have to use something not because it is the best option, but because it is what your team is using, or because the ease of use is worth the performance drawbacks.

Re: JSON for Modern C++

#118
post #21
post #12

Earlier quoted context omitted.

On the other hand, nlohmann/json has a cleaner and more Python-like API, so if you don't care about performance that much, I'd say it's the way to go

Does anyone write C++ and not care about performance?

First of all absolutely, but more importantly who cares about the performance of your json parsing? I can only think of very few applications where that would be relevant at all, even if you care about performance in general.

Re: JSON for Modern C++

#119
post #19

Earlier quoted context omitted.

I lost my mind at this sentence. If feels like a first-class data type because the result of parsing is one of the built-in data types (which can be round-tripped to a similar JSON string). And as soon as you care about serialisation of types it starts feeling incredibly clunky.

If you want to convert it to an object, have you tried using dataclasses? I haven't used them much, but last time I tried them they felt much easier than trying to use the native dict/list/str/int/etc. that gets returned by default.

Yeah. It's the custom serialisation & schema/ctor arg validation that makes it clunky.

Re: JSON for Modern C++

#120
post #74

Earlier quoted context omitted.

> CSV as a format doesn't really exist. RFC-4180

That was created after how many years of CSV in the wild? Nobody disagrees here that parsing CSV in practice is a horrible minefield with lots of manual adjustments.

RFC-4180 is dated 2005 - so your statement that a standard "doesn't exist" has been out of date for 14 years.

Yes of course there was no recognised standard before that. Just like before Greenwich Meantime there was no recognised standard for universal time coordination ...

Post reply on HN