Skip to content

NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE

// (1)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(type, base_type, member...)
// (2)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(type, base_type, member...)
// (3)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...)

// (4)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(type, base_type, member...)
// (5)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, base_type, member...)
// (6)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...)

These macros can be used to simplify the serialization/deserialization of derived types if you want to use a JSON object as serialization and want to use the member variable names as object keys in that object.

  • Macros 1, 2 and 3 are to be defined inside the class/struct to create code for. Like NLOHMANN_DEFINE_TYPE_INTRUSIVE, they can access private members.
  • Macros 4, 5 and 6 are to be defined outside the class/struct to create code for, but inside its namespace. Like NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, they cannot access private members.

The first parameter is the name of the derived class/struct, the second parameter is the name of the base class/struct and all remaining parameters name the members. The base type must be already serializable/deserializable.

  • Macros 1 and 4 will use at during deserialization and will throw out_of_range.403 if a key is missing in the JSON object.
  • Macros 2 and 5 will use value during deserialization and fall back to the default value for the respective type of the member variable if a key in the JSON object is missing. The generated from_json() function default constructs an object and uses its values as the defaults when calling the value function.

Summary:

Need access to private members Need only de-serialization Allow missing values when de-serializing macro
NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE
NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE
NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE
NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE

Parameters

type (in)
name of the type (class, struct) to serialize/deserialize
base_type (in)
name of the base type (class, struct) type is derived from
member (in)
name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list

Default definition

Macros 1 and 2 add two friend functions to the class which take care of the serialization and deserialization:

friend void to_json(nlohmann::json&, const type&);
friend void from_json(const nlohmann::json&, type&);

Macros 4 and 5 add two functions to the namespace which take care of the serialization and deserialization:

void to_json(nlohmann::json&, const type&);
void from_json(const nlohmann::json&, type&);

Macros 3 and 6 add one function to the namespace which take care of the serialization only:

void to_json(nlohmann::json&, const type&);

In first two cases, they call the to_json/from_json functions of the base type before serializing/deserializing the members of the derived type:

class A { /* ... */ };
class B : public A { /* ... */ };

void to_json(nlohmann::json& j, const B& b) {
    nlohmann::to_json(j, static_cast<const A&>(b));
    // ...
}

void from_json(const nlohmann::json& j, B& b) {
    nlohmann::from_json(j, static_cast<A&>(b));
    // ...
}

In the third case, only to_json will be called:

class A { /* ... */ };
class B : public A { /* ... */ };

void to_json(nlohmann::json& j, const B& b) {
    nlohmann::to_json(j, static_cast<const A&>(b));
    // ...
}

Notes

Prerequisites

Implementation limits

See Implementation limits for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, respectively.

Examples

NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE

Consider the following complete example:

#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>

using nlohmann::json;

class A
{
  private:
    double Aa = 0.0;
    double Ab = 0.0;

  public:
    A() = default;
    A(double a, double b) : Aa(a), Ab(b) {}
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(A, Aa, Ab)
};

class B : public A
{
  private:
    int Ba = 0;
    int Bb = 0;

  public:
    B() = default;
    B(int a, int b, double aa, double ab) : A(aa, ab), Ba(a), Bb(b) {}
    NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(B, A, Ba, Bb)
};

int main()
{
    B example(23, 42, 3.142, 1.777);
    json example_json = example;

    std::cout << std::setw(4) << example_json << std::endl;
}

Output:

{
    "Aa": 3.142,
    "Ab": 1.777,
    "Ba": 23,
    "Bb": 42
}

Notes:

  • A and B are default-constructible. This is a requirement for using the macro.
  • A has private members and is not a derived class. Hence, macro NLOHMANN_DEFINE_TYPE_INTRUSIVE is used.
  • As B is a derived class, NLOHMANN_DEFINE_TYPE_INTRUSIVE is not applicable, but NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE must be used.
  • The macro NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE is used inside the class use as NLOHMANN_DEFINE_TYPE_INTRUSIVE.

See also

Version history

  1. Added in version 3.11.x.
  2. Added in version 3.11.x.
  3. Added in version 3.11.x.
  4. Added in version 3.11.x.
  5. Added in version 3.11.x.
  6. Added in version 3.11.x.