Reputation: 1295
I have to write a very basic JSON serializer/deserializer in C++. The goal is to build something similar to this https://github.com/nlohmann/json. Unfortunately I can't use this awesome library because my compiler does not fully support the C++ 11 standard. Switching the compiler is not an option.
I would like to go with an approach close to the following examples. I am writing my idea in some sort of pseudo code, based on the TypeScript Syntax.
I'm imaging a class representing a JSON object, with functions to access it's keys and get some dynamic values from them.
type JSONValue = int | double | string | list | JSONObject | ...;
class JSONObject {
private map: Map<string, JSONValue>;
public set(key: string, value: JSONValue) { ... };
public get(key: string): JSONValue { ... };
public stringify(): string;
}
I think the general concept should be clear. Parsing a JSON string is not the problem. Creating a JSON string is trivial too. But creating a type like JSONValue
in C++ is something I can't wrap my head around.
Probably the way to go are templates, but I need some guidance on how to implement such a "dynamic" type. I would like to get some example on how to approach this problem.
Edit: The code has to work in RAD Studio 10.2.3 with the Clang enhanced compiler. It's hard to tell what this compiler supports so I will test every suggestion and add the limitations to this question as they arise.
Edit 2: Running bcc32x --version
yields the following results:
Embarcadero C++ 7.30 for Win32 Copyright (c) 2012-2017 Embarcadero Technologies, Inc.
Embarcadero Technologies Inc. bcc32x version 3.3.1 (36355.e71d049.f8c4cf9) (based on LLVM 3.3.1)
Target: i686-pc-win32-omf
Thread model: posix
Upvotes: 0
Views: 358
Reputation: 2949
Just have a look at the source code to get some inspiration. For example here you can see how Niels solved that problem: He defines a union json_value
consisting of several pointers to the specific possible types. The concrete type of an json_value
object is then stored in a separate value of type value_t
defined here.
Important: If your compiler doesn't support C++11, the union is not allowed to contain non-trivial members. Since that, it can't contain a std::string
only a pointer to std::string
.
Upvotes: 2
Reputation: 39588
In your case, you don't actually need fully dynamic typing, as JSONValue
can't have any type, just some amount of different types. This is what you would use a union
for:
union JSONValue {
long long integer;
double floating;
std::string string;
...
}
Unions of non-trivially destructible types are however quite unsafe, because you need to make sure that the destructor of string
gets called, if string
is the active member.
If you were using C++17, you could use std::variant
, which is essentially a type-safe union
. Before C++17 (in your case), boost::variant
can be used instead.
Upvotes: 2
Reputation: 1038
If I understand your problem correctly you need something like a union. I recommend std::variant (or boost::variant if compiler doesn't support C++17).
Upvotes: 1