blob: 20670f18101de3ca1640bb34cb1997f1198121ac [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/entity/cpp/json.h>
#include <string>
#include <lib/fxl/logging.h>
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
namespace modular {
constexpr char kEntityTypeProperty[] = "@type";
constexpr char kEntityRefAttribute[] = "@entityRef";
constexpr char kEntityTypeString[] = "com.google.fuchsia.string";
// We use |kEntityTypeUnknown| if the entity doesn't have a type.
constexpr char kEntityTypeUnknown[] = "com.google.fuchsia.unknown";
std::string EntityReferenceToJson(const std::string& ref) {
auto doc = EntityReferenceToJsonDoc(ref);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
return buffer.GetString();
}
rapidjson::Document EntityReferenceToJsonDoc(const std::string& ref) {
// Create an object that looks like:
// {
// "@entityRef": "<ref string>"
// }
rapidjson::Document doc;
doc.SetObject();
rapidjson::Value str;
str.SetString(ref, doc.GetAllocator());
doc.AddMember(kEntityRefAttribute, str, doc.GetAllocator());
return doc;
}
bool EntityReferenceFromJson(const std::string& json, std::string* ref) {
rapidjson::Document doc;
doc.Parse(json);
if (doc.HasParseError())
return false;
return EntityReferenceFromJson(doc, ref);
}
bool EntityReferenceFromJson(const rapidjson::Value& value, std::string* ref) {
if (!value.IsObject() || !value.HasMember(kEntityRefAttribute))
return false;
auto& attr = value[kEntityRefAttribute];
if (!attr.IsString())
return false;
*ref = attr.GetString();
return true;
}
bool ExtractEntityTypesFromJson(const std::string& json,
std::vector<std::string>* const output) {
FXL_CHECK(output != nullptr);
// If the content has the @type attribute, take its contents and populate the
// fuchsia::modular::EntityMetadata appropriately, overriding whatever is
// there.
rapidjson::Document doc;
doc.Parse(json);
if (doc.HasParseError()) {
FXL_LOG(WARNING) << "Error parsing JSON: " << doc.GetParseError();
return false;
}
return ExtractEntityTypesFromJson(doc, output);
}
bool ExtractEntityTypesFromJson(const rapidjson::Value& value,
std::vector<std::string>* const output) {
std::vector<std::string> entity_types;
if (value.IsString()) {
entity_types.emplace_back(kEntityTypeString);
} else if (value.IsObject() && value.HasMember(kEntityTypeProperty)) {
const auto& types = value[kEntityTypeProperty];
if (types.IsString()) {
entity_types.emplace_back(types.GetString());
} else if (types.IsArray()) {
for (uint32_t i = 0; i < types.Size(); ++i) {
if (!types[i].IsString())
return false;
entity_types.emplace_back(types[i].GetString());
}
} else {
return false;
}
} else {
entity_types.push_back(kEntityTypeUnknown);
}
output->swap(entity_types);
return true;
}
} // namespace modular