in velox/type/Variant.cpp [184:303]
std::string variant::toJson() const {
// todo(youknowjack): consistent story around std::stringifying, converting,
// and other basic operations. Stringification logic should not be specific
// to variants; it should be consistent for all map representations
if (isNull()) {
return "null";
}
switch (kind_) {
case TypeKind::MAP: {
auto& map = value<TypeKind::MAP>();
std::string b{};
b += "[";
bool first = true;
for (auto& pair : map) {
if (!first) {
b += ",";
}
b += "{\"key\":";
b += pair.first.toJson();
b += ",\"value\":";
b += pair.second.toJson();
b += "}";
first = false;
}
b += "]";
return b;
}
case TypeKind::ROW: {
auto& row = value<TypeKind::ROW>();
std::string b{};
b += "[";
bool first = true;
for (auto& v : row) {
if (!first) {
b += ",";
}
b += v.toJson();
first = false;
}
b += "]";
return b;
}
case TypeKind::ARRAY: {
auto& array = value<TypeKind::ARRAY>();
std::string b{};
b += "[";
bool first = true;
for (auto& v : array) {
if (!first) {
b += ",";
}
b += v.toJson();
first = false;
}
b += "]";
return b;
}
case TypeKind::VARBINARY: {
auto& str = value<TypeKind::VARBINARY>();
auto encoded = encoding::Base64::encode(str);
return '"' + encoded + '"';
}
case TypeKind::VARCHAR: {
auto& str = value<TypeKind::VARCHAR>();
std::string target;
folly::json::escapeString(str, target, getOpts());
return target;
}
case TypeKind::TINYINT:
case TypeKind::SMALLINT:
case TypeKind::INTEGER:
case TypeKind::BIGINT:
case TypeKind::BOOLEAN: {
auto converted = VariantConverter::convert<TypeKind::VARCHAR>(*this);
if (converted.isNull()) {
return "null";
} else {
return converted.value<TypeKind::VARCHAR>();
}
}
case TypeKind::REAL: {
auto val = value<TypeKind::REAL>();
if (std::isnormal(val)) {
return folly::to<std::string>(val);
} else {
return '"' + folly::to<std::string>(val) + '"';
}
}
case TypeKind::DOUBLE: {
auto val = value<TypeKind::DOUBLE>();
if (std::isnormal(val)) {
return folly::to<std::string>(val);
} else {
return '"' + folly::to<std::string>(val) + '"';
}
}
case TypeKind::TIMESTAMP: {
auto& timestamp = value<TypeKind::TIMESTAMP>();
return '"' + timestamp.toString() + '"';
}
case TypeKind::DATE: {
auto& date = value<TypeKind::DATE>();
return '"' + date.toString() + '"';
}
case TypeKind::OPAQUE: {
// Return expression that we can't parse back - we use toJson for
// debugging only. Variant::serialize should actually serialize the data.
return "\"Opaque<" + value<TypeKind::OPAQUE>().type->toString() + ">\"";
}
case TypeKind::FUNCTION:
case TypeKind::UNKNOWN:
case TypeKind::INVALID:
VELOX_NYI();
}
VELOX_UNSUPPORTED(
"Unsupported: given type {} is not json-ready", mapTypeKindToName(kind_));
}