Using JSON in Modern C++

Using custom types as JSON keys

Can I use a custom type as a key in a JSON object?

Abstract art representing computer programming

The JSON specification only allows strings as keys in objects. However, the nlohmann::json library provides a way to use other types as keys by converting them to strings.

To do this, you need to specialize the nlohmann::adl_serializer<T> struct for your type and provide to_json and from_json functions:

struct Weapon {
  std::string name;
  int damage;
};

namespace nlohmann {
template <>
struct adl_serializer<Weapon> {
  static void to_json(json& j, const Weapon& w) {
    j = w.name;
  }

  static void from_json(const json& j, Weapon& w) {
    w.name = j.get<std::string>();
    w.damage = 10;
  }
};
}

Here we've defined a Weapon struct. The to_json function converts a Weapon to a JSON string (just its name in this case), and from_json converts a JSON string back to a Weapon (setting a default damage of 10 since that information is lost in the string conversion).

Now we can use Weapon as a key in a JSON object:

#include <iostream>
#include <json.hpp>
using json = nlohmann::json;

struct Weapon {
  std::string name;
  int damage;
};

namespace nlohmann {
template <>
struct adl_serializer<Weapon> {
  static void to_json(json& j, const Weapon& w) {
    j = w.name; }

  static void from_json(const json& j, Weapon& w) {
    w.name = j.get<std::string>();
    w.damage = 10;
  }
};
}

int main() {
  json character = {
    {"name", "Lancelot"},
    {"weapon", {{"name", "Sword"}, {"damage", 20}}},
    {Weapon{"Dagger", 5}, "backup weapon"}
  };

  std::cout << character.dump(2);
}
{
  "Dagger": "backup weapon",
  "name": "Lancelot",
  "weapon": {
    "damage": 20,
    "name": "Sword"
  }
}

The Weapon{"Dagger", 5} key was converted to the string "Dagger" in the output JSON.

When using custom types as keys, keep in mind that all the type information is lost in the conversion to string. In this case, the damage property of the "Dagger" key is lost and would be set back to the default of 10 if we were to parse this JSON back into a C++ object.

So while custom type keys are possible, they're not always practical. It's often better to stick with string keys and put the custom types as values in the JSON object.

Answers to questions are automatically generated and may not have been reviewed.

Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved