Free & open source — no account required

v1.2.5-PRICING-19
Web & Frontend • Engineering Documentation

JSON to C++ Struct Converter

This technical guide provides an in-depth analysis of the json to cpp struct engine, best practices for implementation, and data security standards.

JSON to C++ Struct: Generating Structs with nlohmann/json

C++ gives you value semantics, RAII, and std::optional — which makes JSON mapping far safer than raw C pointers. The dominant C++ JSON library is nlohmann/json: header-only, MIT-licensed, and used in tens of thousands of projects. TypeMorph generates a struct with the correct C++ types and a from_json factory that handles optional fields and nested objects. The result compiles on C++17 with no dependencies beyond the single header file.

Live Example: API Response to C++ Struct

// Input JSON
{
  "device_id": "sensor_042",
  "temperature": 23.7,
  "sample_count": 1200,
  "is_active": true,
  "firmware": "2.1.4",
  "error_code": null
}

// Generated C++ (C++17, nlohmann/json)
#include <string>
#include <optional>
#include <cstdint>
#include <nlohmann/json.hpp>

struct Root {
  std::string device_id;
  double temperature;
  int64_t sample_count;
  bool is_active;
  std::string firmware;
  std::optional<std::string> error_code;

  static Root from_json(const nlohmann::json& j) {
    Root obj;
    obj.device_id    = j.at("device_id").get<std::string>();
    obj.temperature  = j.at("temperature").get<double>();
    obj.sample_count = j.at("sample_count").get<int64_t>();
    obj.is_active    = j.at("is_active").get<bool>();
    obj.firmware     = j.at("firmware").get<std::string>();
    if (j.contains("error_code") && !j["error_code"].is_null())
      obj.error_code = j["error_code"].get<std::string>();
    return obj;
  }

  nlohmann::json to_json() const {
    return {
      {"device_id",    device_id},
      {"temperature",  temperature},
      {"sample_count", sample_count},
      {"is_active",    is_active},
      {"firmware",     firmware},
      {"error_code",   error_code.has_value() ? nlohmann::json(*error_code) : nlohmann::json(nullptr)},
    };
  }
};

// Usage
int main() {
  std::string raw = R"({"device_id":"sensor_042","temperature":23.7,...})";
  auto j = nlohmann::json::parse(raw);
  Root r = Root::from_json(j);

  std::cout << r.device_id << ": " << r.temperature << "°C\n";
  if (r.error_code) std::cout << "Error: " << *r.error_code << "\n";
}

C++ Type Mapping from JSON

// JSON → C++ type mapping (C++17)
// "string"  → std::string
// number    → double              (safe default for any JSON number)
// integer   → int64_t             (use int for smaller values, size_t for sizes)
// boolean   → bool
// null      → std::optional<T>   (has_value() == false when JSON is null)
// object    → nested struct
// array     → std::vector<T>

// NLOHMANN_DEFINE_TYPE_INTRUSIVE — macro shortcut for simple structs
// (no optional fields, no custom logic needed)
struct Point {
  double x;
  double y;
  double z;

  NLOHMANN_DEFINE_TYPE_INTRUSIVE(Point, x, y, z)
};

// Usage with macro:
nlohmann::json j = {{"x", 1.0}, {"y", 2.5}, {"z", -0.3}};
Point p = j.get<Point>();                // deserialize
nlohmann::json j2 = p;                    // serialize back

Nested Structs and Arrays

#include <string>
#include <vector>
#include <optional>
#include <nlohmann/json.hpp>

struct Address {
  std::string street;
  std::string city;
  std::optional<std::string> zip;

  static Address from_json(const nlohmann::json& j) {
    Address a;
    a.street = j.at("street").get<std::string>();
    a.city   = j.at("city").get<std::string>();
    if (j.contains("zip") && !j["zip"].is_null())
      a.zip = j["zip"].get<std::string>();
    return a;
  }
};

struct User {
  std::string id;
  std::string name;
  Address address;
  std::vector<std::string> roles;

  static User from_json(const nlohmann::json& j) {
    User u;
    u.id      = j.at("id").get<std::string>();
    u.name    = j.at("name").get<std::string>();
    u.address = Address::from_json(j.at("address"));
    // std::vector deserialization is built-in for primitive types
    if (j.contains("roles"))
      u.roles = j["roles"].get<std::vector<std::string>>();
    return u;
  }

  nlohmann::json to_json() const {
    nlohmann::json j;
    j["id"]      = id;
    j["name"]    = name;
    j["address"] = {
      {"street", address.street},
      {"city",   address.city},
      {"zip",    address.zip.has_value() ? nlohmann::json(*address.zip) : nlohmann::json(nullptr)},
    };
    j["roles"] = roles;
    return j;
  }
};

HTTP Fetch with libcurl + nlohmann/json

#include <string>
#include <stdexcept>
#include <curl/curl.h>
#include <nlohmann/json.hpp>

// libcurl write callback
static size_t write_cb(char *ptr, size_t size, size_t nmemb, std::string *data) {
  data->append(ptr, size * nmemb);
  return size * nmemb;
}

std::string http_get(const std::string& url) {
  CURL *curl = curl_easy_init();
  if (!curl) throw std::runtime_error("curl init failed");

  std::string response;
  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

  CURLcode res = curl_easy_perform(curl);
  curl_easy_cleanup(curl);
  if (res != CURLE_OK) throw std::runtime_error(curl_easy_strerror(res));
  return response;
}

// Full fetch-and-parse example
int main() {
  std::string body = http_get("https://api.example.com/users/usr_042");
  auto j = nlohmann::json::parse(body);
  User user = User::from_json(j);
  std::cout << "Name: " << user.name << "\n";
}

Frequently Asked Questions

Why nlohmann/json over RapidJSON or simdjson? nlohmann/json is the most ergonomic: it integrates naturally with C++ containers and operator overloads, requires no schema compilation step, and is a single header drop-in. RapidJSON is faster (SAX-style, zero-copy) and better for high-throughput parsing where allocations matter. simdjson is the fastest (SIMD-accelerated) for read-only use cases. For typical API integration work, nlohmann/json's developer ergonomics win — switch to RapidJSON or simdjson only when profiling shows JSON parsing is a bottleneck.

What does j.at("key") vs j["key"] do? j.at("key") throws nlohmann::json::out_of_range if the key is missing — use this for required fields so you get a clear error instead of a default-constructed value. j["key"] creates the key with a null value if it doesn't exist, which silently produces wrong data. In the generated from_json, required fields use .at() and optional fields use .contains() first.

How do I handle arrays of objects? nlohmann/json's .get<std::vector<T>>() works automatically for primitive types. For std::vector<YourStruct>, define a from_json(const nlohmann::json&, YourStruct&) free function and register it via the ADL pattern, or iterate manually: for (auto& item : j["items"]) vec.push_back(YourStruct::from_json(item));

Is my JSON sent to a server? No. TypeMorph runs entirely in your browser — none of your data leaves your machine.

Developer FAQ

Is the processing local-only?

Absolutely. TypeMorph operates entirely within your browser's sandbox. We use Web Workers for high-performance computation without ever transmitting your JSON, SQL, or API data to a remote server.

Can I use this for enterprise projects?

Yes. The tool is designed for professional software engineers who require GDPR compliance and data privacy. It is trusted by developers at top-tier startups and financial institutions.