// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "jsoncpp_json_serializer.h" #include "null_json_serializer.h" #include #include #include namespace dap { namespace json { JsonCppDeserializer::JsonCppDeserializer(const std::string& str) : json(new Json::Value(JsonCppDeserializer::parse(str))), ownsJson(true) {} JsonCppDeserializer::JsonCppDeserializer(const Json::Value* json) : json(json), ownsJson(false) {} JsonCppDeserializer::~JsonCppDeserializer() { if (ownsJson) { delete json; } } bool JsonCppDeserializer::deserialize(dap::boolean* v) const { if (!json->isBool()) { return false; } *v = json->asBool(); return true; } bool JsonCppDeserializer::deserialize(dap::integer* v) const { if (!json->isInt64()) { return false; } *v = json->asInt64(); return true; } bool JsonCppDeserializer::deserialize(dap::number* v) const { if (!json->isNumeric()) { return false; } *v = json->asDouble(); return true; } bool JsonCppDeserializer::deserialize(dap::string* v) const { if (!json->isString()) { return false; } *v = json->asString(); return true; } bool JsonCppDeserializer::deserialize(dap::object* v) const { v->reserve(json->size()); for (auto i = json->begin(); i != json->end(); i++) { JsonCppDeserializer d(&*i); dap::any val; if (!d.deserialize(&val)) { return false; } (*v)[i.name()] = val; } return true; } bool JsonCppDeserializer::deserialize(dap::any* v) const { if (json->isBool()) { *v = dap::boolean(json->asBool()); } else if (json->type() == Json::ValueType::realValue) { // json->isDouble() returns true for integers as well, so we need to // explicitly look for the realValue type. *v = dap::number(json->asDouble()); } else if (json->isInt64()) { *v = dap::integer(json->asInt64()); } else if (json->isString()) { *v = json->asString(); } else if (json->isObject()) { dap::object obj; if (!deserialize(&obj)) { return false; } *v = obj; } else if (json->isArray()) { dap::array arr; if (!deserialize(&arr)) { return false; } *v = arr; } else if (json->isNull()) { *v = null(); } else { return false; } return true; } size_t JsonCppDeserializer::count() const { return json->size(); } bool JsonCppDeserializer::array( const std::function& cb) const { if (!json->isArray()) { return false; } for (const auto& value : *json) { JsonCppDeserializer d(&value); if (!cb(&d)) { return false; } } return true; } bool JsonCppDeserializer::field( const std::string& name, const std::function& cb) const { if (!json->isObject()) { return false; } auto value = json->find(name.data(), name.data() + name.size()); if (value == nullptr) { return cb(&NullDeserializer::instance); } JsonCppDeserializer d(value); return cb(&d); } Json::Value JsonCppDeserializer::parse(const std::string& text) { Json::CharReaderBuilder builder; auto jsonReader = std::unique_ptr(builder.newCharReader()); Json::Value json; std::string error; if (!jsonReader->parse(text.data(), text.data() + text.size(), &json, &error)) { // cppdap expects that the JSON layer does not throw exceptions. std::abort(); } return json; } JsonCppSerializer::JsonCppSerializer() : json(new Json::Value()), ownsJson(true) {} JsonCppSerializer::JsonCppSerializer(Json::Value* json) : json(json), ownsJson(false) {} JsonCppSerializer::~JsonCppSerializer() { if (ownsJson) { delete json; } } std::string JsonCppSerializer::dump() const { Json::StreamWriterBuilder writer; return Json::writeString(writer, *json); } bool JsonCppSerializer::serialize(dap::boolean v) { *json = (bool)v; return true; } bool JsonCppSerializer::serialize(dap::integer v) { *json = (Json::LargestInt)v; return true; } bool JsonCppSerializer::serialize(dap::number v) { *json = (double)v; return true; } bool JsonCppSerializer::serialize(const dap::string& v) { *json = v; return true; } bool JsonCppSerializer::serialize(const dap::object& v) { if (!json->isObject()) { *json = Json::Value(Json::objectValue); } for (auto& it : v) { JsonCppSerializer s(&(*json)[it.first]); if (!s.serialize(it.second)) { return false; } } return true; } bool JsonCppSerializer::serialize(const dap::any& v) { if (v.is()) { *json = (bool)v.get(); } else if (v.is()) { *json = (Json::LargestInt)v.get(); } else if (v.is()) { *json = (double)v.get(); } else if (v.is()) { *json = v.get(); } else if (v.is()) { // reachable if dap::object nested is inside other dap::object return serialize(v.get()); } else if (v.is()) { } else { // reachable if array or custom serialized type is nested inside other auto type = get_any_type(v); auto value = get_any_val(v); if (type && value) { return type->serialize(this, value); } return false; } return true; } bool JsonCppSerializer::array(size_t count, const std::function& cb) { *json = Json::Value(Json::arrayValue); for (size_t i = 0; i < count; i++) { JsonCppSerializer s(&(*json)[Json::Value::ArrayIndex(i)]); if (!cb(&s)) { return false; } } return true; } bool JsonCppSerializer::object( const std::function& cb) { struct FS : public FieldSerializer { Json::Value* const json; FS(Json::Value* json) : json(json) {} bool field(const std::string& name, const SerializeFunc& cb) override { JsonCppSerializer s(&(*json)[name]); auto res = cb(&s); if (s.removed) { json->removeMember(name); } return res; } }; *json = Json::Value(Json::objectValue); FS fs{json}; return cb(&fs); } void JsonCppSerializer::remove() { removed = true; } } // namespace json } // namespace dap