#include "JsonStream.h" #include namespace resource_api { JsonStream::JsonStream(): mSerialise(true), mDataType(TYPE_UNDEFINED), mArrayNextRead(0), mIsOk(true), mChild(NULL) { } JsonStream::~JsonStream() { deleteCurrentChild(); } void JsonStream::setJsonString(std::string jsonStr) { mRawString = jsonStr; // have to delay the deserialisation, because this stream can also be a raw data stream without json // can find this out when others atucally call the operators mSerialise = false; } std::string JsonStream::getJsonString() { deleteCurrentChild(); if(mIsOk) { switch(mDataType) { case TYPE_UNDEFINED: return ""; case TYPE_ARRAY: return json::Serialize(mArray); case TYPE_OBJECT: return json::Serialize(mObject); case TYPE_RAW: return mRawString; default: return ""; } } std::cerr << "JsonStream::getJsonString() Warning: stream not ok, will return empty string." << std::endl; return ""; } //----------Stream Interface --------------- //----------Array--------------- StreamBase& JsonStream::operator<<(ValueReference value) { if(serialise()) { setType(TYPE_ARRAY); mArray.push_back(value.value); } else { if(checkDeserialisation() && arrayBoundsOk()) { valueToBool(mArray[mArrayNextRead], value.value); mArrayNextRead++; } } return *this; } StreamBase& JsonStream::operator<<(ValueReference value) { if(serialise()) { setType(TYPE_ARRAY); mArray.push_back(value.value); } else { if(checkDeserialisation() && arrayBoundsOk()) { valueToInt(mArray[mArrayNextRead], value.value); mArrayNextRead++; } } return *this; } StreamBase& JsonStream::operator<<(ValueReference value) { if(serialise()) { setType(TYPE_ARRAY); mArray.push_back(value.value); } else { if(checkDeserialisation() && arrayBoundsOk()) { valueToDouble(mArray[mArrayNextRead], value.value); mArrayNextRead++; } } return *this; } StreamBase& JsonStream::operator<<(ValueReference value) { if(serialise()) { setType(TYPE_ARRAY); mArray.push_back(value.value); } else { if(checkDeserialisation() && arrayBoundsOk()) { valueToString(mArray[mArrayNextRead], value.value); mArrayNextRead++; } } return *this; } StreamBase& JsonStream::getStreamToMember() { setType(TYPE_ARRAY); deleteCurrentChild(); mChild = new JsonStream(); if(!serialise()) { if(checkDeserialisation() && arrayBoundsOk()) { mChild->mValue = mArray[mArrayNextRead]; mArrayNextRead++; } } return *mChild; } //----------Object--------------- StreamBase& JsonStream::operator<<(KeyValueReference keyValue) { if(serialise()) { setType(TYPE_OBJECT); mObject[keyValue.key] = keyValue.value; } else { if(checkDeserialisation() && checkObjectMember(keyValue.key)) { valueToBool(mObject[keyValue.key], keyValue.value); } } return *this; } StreamBase& JsonStream::operator<<(KeyValueReference keyValue) { if(serialise()) { setType(TYPE_OBJECT); mObject[keyValue.key] = keyValue.value; } else { if(checkDeserialisation() && checkObjectMember(keyValue.key)) { valueToInt(mObject[keyValue.key], keyValue.value); } } return *this; } StreamBase& JsonStream::operator<<(KeyValueReference keyValue) { if(serialise()) { setType(TYPE_OBJECT); mObject[keyValue.key] = keyValue.value; } else { if(checkDeserialisation() && checkObjectMember(keyValue.key)) { valueToDouble(mObject[keyValue.key], keyValue.value); } } return *this; } StreamBase& JsonStream::operator<<(KeyValueReference keyValue) { if(serialise()) { setType(TYPE_OBJECT); mObject[keyValue.key] = keyValue.value; } else { if(checkDeserialisation() && checkObjectMember(keyValue.key)) { valueToString(mObject[keyValue.key], keyValue.value); } } return *this; } // usefull if the new object member should be an array or object // the reference should be at least valid until another method of this class gets called StreamBase& JsonStream::getStreamToMember(std::string name) { setType(TYPE_OBJECT); deleteCurrentChild(); mChildKey = name; mChild = new JsonStream(); if(!serialise()) { if(checkDeserialisation() && checkObjectMember(name)) { mChild->mValue = mObject[name]; } } return *mChild; } // make a binay data object (not a real object, just binary data) StreamBase& JsonStream::operator<<(std::vector& data) { if(serialise()) { if((mDataType == TYPE_UNDEFINED)||(mDataType == TYPE_RAW)) { mDataType = TYPE_RAW; mRawString = std::string(data.begin(), data.end()); } else { mErrorLog += "Error: trying to set raw data while the type of this object is already another type\n"; mIsOk = false; } } else { if((mDataType == TYPE_UNDEFINED)||(mDataType == TYPE_RAW)) { mDataType = TYPE_RAW; data = std::vector(mRawString.begin(), mRawString.end()); } else { mErrorLog += "Error: trying to read raw data while the type of this object is already another type\n"; mIsOk = false; } } return *this; } // return true if there are more members in this object/array // useful for array reading bool JsonStream::hasMore() { return arrayBoundsOk(); } bool JsonStream::serialise() { return mSerialise; } bool JsonStream::isOK() { return mIsOk; } void JsonStream::setError() { mIsOk = false; } /* void JsonStream::addLogMsg(std::string msg) {} */ void JsonStream::addErrorMsg(std::string msg) { mErrorLog += msg; } std::string JsonStream::getLog() { return "not implemented yet"; } std::string JsonStream::getErrorLog() { return mErrorLog; } bool JsonStream::isRawData() { return mDataType == TYPE_RAW; } std::string JsonStream::getRawData() { return mRawString; } void JsonStream::setType(DataType type) { if((mDataType == TYPE_UNDEFINED)||(mDataType == type)) { mDataType = type; } else { mIsOk = false; mErrorLog += "JsonStream::setType() Error: type alread set to another type\n"; } } bool JsonStream::checkObjectMember(std::string key) { if(mDataType == TYPE_OBJECT) { if(mObject.HasKey(key)) { return true; } else { mErrorLog += "JsonStream::checkObjectMember() Warning: missing key \""+key+"\"\n"; return false; } } else { mIsOk = false; mErrorLog += "JsonStream::checkObjectMember() Error: type is not TYPE_OBJECT\n"; return false; } } bool JsonStream::arrayBoundsOk() { if(checkDeserialisation()) { if(mDataType == TYPE_ARRAY) { if(mArrayNextRead < mArray.size()) { return true; } else { return false; } } else { mIsOk = false; mErrorLog += "JsonStream::arrayBoundsOk() Error: type is not TYPE_ARRAY\n"; return false; } } return false; } bool JsonStream::checkDeserialisation() { if(mDataType != TYPE_RAW) { if(mDataType == TYPE_UNDEFINED) { if((mValue.GetType() == json::NULLVal) && mRawString != "") { mValue = json::Deserialize(mRawString); } if(mValue.GetType() == json::ObjectVal) { mDataType = TYPE_OBJECT; mObject = mValue; return true; } else if(mValue.GetType() == json::ArrayVal) { mDataType = TYPE_ARRAY; mArray = mValue; return true; } else { mIsOk = false; mErrorLog += "JsonStream::checkDeserialisation() Error: deserialisation did not end with an object or array\n"; return false; } } else { // already deserialised return true; } } else { mIsOk = false; mErrorLog += "JsonStream::checkDeserialisation() Error: type is TYPE_RAW\n"; return false; } } void JsonStream::valueToBool(json::Value &value, bool &boolean) { if(value.GetType() == json::BoolVal) { boolean = value; } else { mIsOk = false; mErrorLog += "JsonStream::valueToBool() Error: wrong type\n"; } } void JsonStream::valueToInt(json::Value &value, int &integer) { if(value.GetType() == json::IntVal) { integer = value; } else { mIsOk = false; mErrorLog += "JsonStream::valueToInt() Error: wrong type\n"; } } void JsonStream::valueToDouble(json::Value &value, double &doubleVal) { if(value.IsNumeric()) { doubleVal = value; } else { mIsOk = false; mErrorLog += "JsonStream::valueToDouble() Error: wrong type\n"; } } void JsonStream::valueToString(json::Value &value, std::string& str) { if(value.GetType() == json::StringVal) { str = value.ToString(); } else { mIsOk = false; mErrorLog += "JsonStream::valueToString() Error: wrong type\n"; } } void JsonStream::deleteCurrentChild() { if(mChild) { if(serialise()) { if(mDataType == TYPE_ARRAY) { // don't add empty value if(mChild->getJsonValue().GetType() != json::NULLVal) mArray.push_back(mChild->getJsonValue()); } else if(mDataType == TYPE_OBJECT) { mObject[mChildKey] = mChild->getJsonValue(); } else { mErrorLog += "JsonStream::deleteCurrentChild() Error: cannot add child because own type is wrong\n"; } } else { // don't have to do anything for deserialisation } delete mChild; mChild = NULL; } } json::Value JsonStream::getJsonValue() { // remove the child and add it to own data deleteCurrentChild(); switch(mDataType) { case TYPE_UNDEFINED: return json::Value(); case TYPE_ARRAY: return mArray; case TYPE_OBJECT: return mObject; case TYPE_RAW: return mRawString; default: return json::Value(); } } } // namespace resource_api