Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue when dumping a vector of derived classes #4462

Open
2 tasks done
myermo opened this issue Sep 18, 2024 · 3 comments
Open
2 tasks done

Issue when dumping a vector of derived classes #4462

myermo opened this issue Sep 18, 2024 · 3 comments
Labels
solution: invalid the issue is not related to the library

Comments

@myermo
Copy link

myermo commented Sep 18, 2024

Description

I need to serialize a vector composed by derived classes. I have a Container class which holds two variables, one of them being a std::vector<Base>. When dumping the contents of the vector, only the members of the Base class are detected, and the members of the Derived classes are omitted.

Reproduction steps

Just execute the example provided.

https://godbolt.org/z/KbxKs688Y

Expected vs. actual results

Actual Result
{ "Container": { "a": 2, "data": [ { "b": 3 }, { "b": 5 } ] } }

Expected Result
{ "Container": { "a": 2, "data": [ { "b": 3, "d": 4 }, { "b": 5, "d": 6 } ] } }

Minimal code example

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

using json = nlohmann::ordered_json;

// Minimum example of the bug
struct Base
{
  int b{};

  Base(int b) : b(b) {};
};

struct Derived : public Base
{
  int d{};

  Derived(int b, int d) : Base(b), d(d) {};
};

struct Container
{
  int a{};
  std::vector<std::shared_ptr<Base>> v{};

  Container(int a, std::vector<std::shared_ptr<Base>> v) : a(a), v(v) {};
};

void to_json(json& j, const std::shared_ptr<Base>& b)
{
  j = json{{"b", b->b}};
}

void to_json(json& j, const std::shared_ptr<Derived>& d)
{
  j = json{{"b", d->b}};
  j.update("d", d->d);
}

void to_json(json& j, const std::shared_ptr<Container>& c)
{
  j = json{ { "a", c->a } , { "data", c->v } };
}

void createOutputJson()
{
  json j;

  auto d1 = std::make_shared<Derived>(3, 4);
  auto d2 = std::make_shared<Derived>(5, 6);

  std::vector<std::shared_ptr<Base>> v2 = {d1, d2};

  auto C = std::make_shared<Container>(2, v2);

  j["Container"] = C;

  std::cout << j.dump(4) << std::endl;
}

int main() {
    createOutputJson();
}


### Error messages

```Shell
N/A

Compiler and operating system

Arch Linux, GCC 14.2.1 and CLANG 19.1.0

Library version

b36f4c4

Validation

@nlohmann
Copy link
Owner

Do not use curly braces to initialize a JSON value, see the first item of the FAQ: https://json.nlohmann.me/home/faq/

@nlohmann nlohmann added solution: invalid the issue is not related to the library and removed kind: bug labels Sep 18, 2024
@myermo
Copy link
Author

myermo commented Sep 18, 2024

I did the changes , but the issue persists. It seems like the to_json() function in the derived class is never called.

See new code: https://godbolt.org/z/b9f7eezT9

@gregmarr
Copy link
Contributor

gregmarr commented Sep 18, 2024

I did the changes , but the issue persists. It seems like the to_json() function in the derived class is never called.

That's correct, you have shared_ptr<Base>, so that's what's called. You have to do all the work there to handle the derived class, such as calling a virtual function in Base. That includes doing something like writing out a type identifier string or enum value so you know what type to instantiate in from_json<Base>.

I believe that there's an example of this in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
solution: invalid the issue is not related to the library
Projects
None yet
Development

No branches or pull requests

3 participants