vendredi 21 juin 2019

unable to determine rapidjson type / difficult to read triple nested strings

I'm trying to use cereal to deserialize a JSON message. The (current) message structure is as follows:

"A":"B",
"C":{"D":"E","F":"G","H":"I"}
"J":"K",
"L":"M"
"N":{"O":{"P":"Q"}}}


The most important piece of data is "Q." I can read all the normal strings easily. I was able to read the top-level items easily. I eventually was able to read "D"-"I" by treating "C" as an array (despite the lack of "["and "]"). However, I am unable to archive "N" as a string, array, vector, or object. It simply fails the respective IsString(), IsObject(), etc check on the iarchive(C); line. I see a GetType(), but I don't know to call that on "N" because anything I try to do with "N" fails.

I then was able to break the string down to just

{"O":{"P":"Q"}}

great, so just "C", but even simpler. Unfortunately, I had the same issue as before.

I then broke it down to just {"P":"Q"} and was able to finally get the value of Q via iarchive(value)

std::string msgtype,protocol_version, command, radio1_frequency,value;
    std::string unit_id[3];
    std::stringstream ss(msg->get_payload());
    {//at this point, ^ss has  the same format as outlined above, from "A" to "Q."
        cereal::JSONInputArchive iarchive(ss);
        iarchive(CEREAL_NVP(msgtype), CEREAL_NVP(protocol_version), CEREAL_NVP(command),CEREAL_NVP(unit_id));<-----------------------
    }
    rapidjson::Document doc;
    doc.Parse((msg->get_payload()).c_str());
    const rapidjson::Value& vars = doc["variables"];//<--this string is N
    rapidjson::StringBuffer sb;
    rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
    vars.Accept(writer);
    std::stringstream sst(sb.GetString());
    std::cout << sst.str() << "\n"; //here, sst has {"O":{"P":"Q"}}
    doc.Parse(sb.GetString());

    const rapidjson::Value& val = doc["radio1_frequency"];//<--this string is O
    sb.Clear();
    rapidjson::Writer<rapidjson::StringBuffer> writerTwo(sb);
    val.Accept(writerTwo);
    std::cout << sb.GetString() << "\n";//ss3 will now have {"P":"Q"} 
    std::stringstream ss3(sb.GetString());
    {
        cereal::JSONInputArchive iarchive(ss3);
        iarchive((value));
        std::cout << value << '\n';//Q
    }

if I add ,CEREAL_NVP(variables) to the line with the arrow, I get the following output:

terminate called after throwing an instance of 'cereal::RapidJSONException'
  what():  rapidjson internal assertion failure: IsString()

Child terminated with signal = 0x6 (SIGABRT)

To be clear, I get the result that I want, Q. I just feel like there must be a better way. I feel like the root of the problem is that I am unable to identify what type N is. Since I don't know the type, I don't know how to properly archive it in cereal. What can I do better inside the realm of C++11 and cereal, which uses rapidjson?

I wonder if it is because "O" has a number in the middle of the string and that is throwing it off. I should hope not because that's a valid string I believe

Aucun commentaire:

Enregistrer un commentaire