mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-11 18:14:03 +00:00
JSONRowOutputStream [#CONV-7445]
This commit is contained in:
parent
e03e85184f
commit
8685024166
39
dbms/include/DB/DataStreams/JSONRowOutputStream.h
Normal file
39
dbms/include/DB/DataStreams/JSONRowOutputStream.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/Core/Block.h>
|
||||||
|
#include <DB/IO/WriteBuffer.h>
|
||||||
|
#include <DB/IO/WriteBufferValidUTF8.h>
|
||||||
|
#include <DB/DataStreams/IRowOutputStream.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Поток для вывода данных в формате JSON.
|
||||||
|
*/
|
||||||
|
class JSONRowOutputStream : public IRowOutputStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_);
|
||||||
|
|
||||||
|
void writeField(const Field & field);
|
||||||
|
void writeFieldDelimiter();
|
||||||
|
void writeRowStartDelimiter();
|
||||||
|
void writeRowEndDelimiter();
|
||||||
|
void writePrefix();
|
||||||
|
void writeSuffix();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef std::vector<NameAndTypePair> NamesAndTypesVector;
|
||||||
|
|
||||||
|
//WriteBufferValidUTF8 ostr;
|
||||||
|
WriteBuffer & ostr;
|
||||||
|
size_t field_number;
|
||||||
|
size_t row_count;
|
||||||
|
NamesAndTypesVector fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
94
dbms/src/DataStreams/JSONRowOutputStream.cpp
Normal file
94
dbms/src/DataStreams/JSONRowOutputStream.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include <DB/DataStreams/JSONRowOutputStream.h>
|
||||||
|
|
||||||
|
#include <DB/IO/WriteHelpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using Poco::SharedPtr;
|
||||||
|
|
||||||
|
|
||||||
|
JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_)
|
||||||
|
: ostr(ostr_), field_number(0), row_count(0)
|
||||||
|
{
|
||||||
|
NamesAndTypesList columns(sample_.getColumnsList());
|
||||||
|
fields.assign(columns.begin(), columns.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writePrefix()
|
||||||
|
{
|
||||||
|
writeString("{\n", ostr);
|
||||||
|
writeString("\t\"meta\":\n", ostr);
|
||||||
|
writeString("\t[\n", ostr);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < fields.size(); ++i)
|
||||||
|
{
|
||||||
|
writeString("\t\t{\n", ostr);
|
||||||
|
|
||||||
|
writeString("\t\t\t\"name\": ", ostr);
|
||||||
|
writeDoubleQuotedString(fields[i].first, ostr);
|
||||||
|
writeString(",\n", ostr);
|
||||||
|
writeString("\t\t\t\"type\": ", ostr);
|
||||||
|
writeDoubleQuotedString(fields[i].second->getName(), ostr);
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
|
||||||
|
writeString("\t\t}", ostr);
|
||||||
|
if (i + 1 < fields.size())
|
||||||
|
writeChar(',', ostr);
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeString("\t],\n", ostr);
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
writeString("\t\"data\":\n", ostr);
|
||||||
|
writeString("\t[\n", ostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writeField(const Field & field)
|
||||||
|
{
|
||||||
|
writeString("\t\t\t", ostr);
|
||||||
|
writeDoubleQuotedString(fields[field_number].first, ostr);
|
||||||
|
writeString(": ", ostr);
|
||||||
|
fields[field_number].second->serializeTextQuoted(field, ostr);
|
||||||
|
++field_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writeFieldDelimiter()
|
||||||
|
{
|
||||||
|
writeString(",\n", ostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writeRowStartDelimiter()
|
||||||
|
{
|
||||||
|
if (row_count > 0)
|
||||||
|
writeString(",\n", ostr);
|
||||||
|
writeString("\t\t{\n", ostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writeRowEndDelimiter()
|
||||||
|
{
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
writeString("\t\t}", ostr);
|
||||||
|
field_number = 0;
|
||||||
|
++row_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONRowOutputStream::writeSuffix()
|
||||||
|
{
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
writeString("\t],\n", ostr);
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
writeString("\t\"rows\": ", ostr);
|
||||||
|
writeIntText(row_count, ostr);
|
||||||
|
writeChar('\n', ostr);
|
||||||
|
writeString("}\n", ostr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
dbms/src/DataStreams/tests/json_streams.cpp
Normal file
80
dbms/src/DataStreams/tests/json_streams.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/assign/list_inserter.hpp>
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/IO/ReadBufferFromIStream.h>
|
||||||
|
#include <DB/IO/WriteBufferFromOStream.h>
|
||||||
|
|
||||||
|
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||||
|
#include <DB/DataTypes/DataTypeString.h>
|
||||||
|
#include <DB/DataTypes/DataTypeFixedString.h>
|
||||||
|
#include <DB/DataTypes/DataTypeDateTime.h>
|
||||||
|
|
||||||
|
#include <DB/DataStreams/TabSeparatedRowInputStream.h>
|
||||||
|
#include <DB/DataStreams/TabSeparatedBlockOutputStream.h>
|
||||||
|
#include <DB/DataStreams/JSONRowOutputStream.h>
|
||||||
|
#include <DB/DataStreams/copyData.h>
|
||||||
|
|
||||||
|
#include <DB/Storages/StorageLog.h>
|
||||||
|
|
||||||
|
|
||||||
|
using Poco::SharedPtr;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DB::NamesAndTypesListPtr names_and_types_list = new DB::NamesAndTypesList;
|
||||||
|
|
||||||
|
boost::assign::push_back(*names_and_types_list)
|
||||||
|
("WatchID", new DB::DataTypeUInt64)
|
||||||
|
("ClientIP", new DB::DataTypeUInt32)
|
||||||
|
("Referer", new DB::DataTypeString)
|
||||||
|
("URL", new DB::DataTypeString)
|
||||||
|
("IsLink", new DB::DataTypeUInt8)
|
||||||
|
("OriginalUserAgent", new DB::DataTypeString)
|
||||||
|
("EventTime", new DB::DataTypeDateTime)
|
||||||
|
;
|
||||||
|
|
||||||
|
SharedPtr<DB::DataTypes> data_types = new DB::DataTypes;
|
||||||
|
|
||||||
|
for (DB::NamesAndTypesList::const_iterator it = names_and_types_list->begin(); it != names_and_types_list->end(); ++it)
|
||||||
|
data_types->push_back(it->second);
|
||||||
|
|
||||||
|
DB::Block sample;
|
||||||
|
for (DB::NamesAndTypesList::const_iterator it = names_and_types_list->begin(); it != names_and_types_list->end(); ++it)
|
||||||
|
{
|
||||||
|
DB::ColumnWithNameAndType elem;
|
||||||
|
elem.name = it->first;
|
||||||
|
elem.type = it->second;
|
||||||
|
elem.column = elem.type->createColumn();
|
||||||
|
sample.insert(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ifstream istr("json_test.in");
|
||||||
|
std::ofstream ostr("json_test.out");
|
||||||
|
|
||||||
|
DB::ReadBufferFromIStream in_buf(istr);
|
||||||
|
DB::WriteBufferFromOStream out_buf(ostr);
|
||||||
|
|
||||||
|
DB::TabSeparatedRowInputStream row_input(in_buf, sample, true, true);
|
||||||
|
DB::JSONRowOutputStream row_output(out_buf, sample);
|
||||||
|
|
||||||
|
DB::copyData(row_input, row_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const DB::Exception & e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << ", " << e.displayText() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user