2

This is my json string

{
    "connectionString" : "MyConnectionString",
    "value" :"MyVal"
}

This is my class

        struct Settings
        {
            std::string connectionString;
            std::string value;

            template<class Archive>
            void serialize(Archive& ar)
            {
                    ar(CEREAL_NVP(connectionString),
                    CEREAL_NVP(value)
                );
            }
        };

And this is what I am doing:

            std::ifstream ifs("Settings.json");
            std::string content((std::istreambuf_iterator<char>(ifs)),(std::istreambuf_iterator<char>())); // Yes this is valid - The content gets populated
            
            Settings settings;
            {
                cereal::JSONInputArchive archive_in(ifs);
                archive_in(settings); //<<-----Exception here - Unhandled exception
            }

The above solution would works only if my json string was this (i.e) if all the json string was an object of another key.

{
    "SomeThing" :{
                "connectionString" : "MyConnectionString",
                "value" :"MyVal"
       }
}

My question is how can I make my actual json string work (without wrapping it in an object)? I currently have this in a json file

{
    "connectionString" : "MyConnectionString",
    "value" :"MyVal"
}

and I wanted to know the best approach of deserializing this into an object ?

Rajeshwar
  • 11,179
  • 26
  • 86
  • 158
  • What exception is it? Did you look up the documentation for `archive_in`'s call operator to find out what it means in that context? Have you verified that the stream `ifs` is valid? Have you verified that the string `content` contains what you think it should? Why do you create a stream, extract its "contents", then immediately create another stream from them? Why not just pass `ifs` to `archive_in`'s constructor? So many questions... – Asteroids With Wings Nov 16 '20 at 20:42
  • @AsteroidsWithWings I used ifs instead of creating a stream. Also yes the content is valid. I also added the type of exception i am getting – Rajeshwar Nov 16 '20 at 21:44
  • Okay now what about the rest – Asteroids With Wings Nov 16 '20 at 21:49
  • @AsteroidsWithWings can you tell me what I am missing ? I think I did answer all your questions ? Please correct me if I am wrong – Rajeshwar Nov 16 '20 at 21:55
  • You answered three of them. I asked more than three. – Asteroids With Wings Nov 16 '20 at 21:57

1 Answers1

1

The code expecting that outer object is put there by the default JSON "prologue" and "epilogue" behavior:

https://github.com/USCiLab/cereal/blob/10d9a29c225fe9a843d043bfe9f13c5f958844dc/include/cereal/archives/json.hpp#L837

From the documentation:

These functions are given a reference to the active archive and a constant reference to the type being serialized. Careful specialization of prologue and epilogue allows for archives to exercise special behaviors without having to re-implement serialization functions for types. This lets us make the type support fairly generic. For example, cereal::XMLOutputArchive (<cereal/archives/xml.hpp>) makes use of these functions to start and finish nodes in its in-memory tree.

If you add in your code an overload for your type that does nothing:

void epilogue(cereal::JSONInputArchive&, const Settings&) { }
void prologue(cereal::JSONInputArchive&, const Settings&) { }

It won't try to parse an outer object

parktomatomi
  • 3,851
  • 1
  • 14
  • 18
  • Awesome that did the trick !! Also any chance you might know why this doesnt work if the variables in Settings class are made static ? – Rajeshwar Nov 19 '20 at 09:33
  • Not off the top of my head, but it smells like something related to [argument dependent lookup](https://en.cppreference.com/w/cpp/language/adl). – parktomatomi Nov 19 '20 at 09:40
  • 1
    static data worked fine for me. But the `CEREAL_NVP` macro failed due to the scope (`::`) messing with the property name. Had to use `::cereal::make_nvp("name", Settings::value)` – parktomatomi Nov 19 '20 at 09:55