0

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

edit: I forgot to mention that "O" can change. so I won't be able to hardcode that in doc["N"]["O"]["P"]

pthien
  • 23
  • 1
  • 8
  • Coma seems missing at end of some lines... – Jarod42 Jun 21 '19 at 16:33
  • You don't have to rewrite json to get inner value, `doc["N"]["O"]["P"]` should return json value with `"Q"`. – Jarod42 Jun 21 '19 at 16:35
  • I don't get your comma comment. but thank you, that second comment was it. saved me 20 ugly LOC and processor time as well. I didn't catch this from the documentation because they only go one level e.g. ```doc["N"]``` want to submit as answer? – pthien Jun 21 '19 at 16:48
  • oh I forgot to mention something. see edit. I can hardcode that for this specific message, but there are many different messages. your solution does not solve the unknown type issue, and that issue will block your solution for other messages. so it's definitely an improvement but not a solution for all cases – pthien Jun 21 '19 at 16:58
  • You have `"J":"K",` and `"L":"M"`. one as comma at end of line, not the other. – Jarod42 Jun 21 '19 at 17:23
  • You can still do `const std::string dynamic_key = /*..*/; doc[dynamic_key]`. – Jarod42 Jun 21 '19 at 17:24
  • thanks. fixed the formatting. as for the dynamic key, if I'm reading this correctly, I'll need to know what the dynamic key will be. I have to read that from the message. But I wouldn't have any problems in the first place if I could archive "N" or "O" properly. again, rapidjson isn't recognizing them as strings nor as arrays. – pthien Jun 21 '19 at 17:54

0 Answers0