Hi Simon, I recently wrote a tool to convert an arbitrary SQLite result set to properly typed json key/value pairs, using the SQLite type affinity of the objects. Though the code is in C++. But it gives an idea how simple this is when with a JSON library (I'm using RapidJson). Rapidjson can also be used in buffered mode, so it's also easily possible to write out large tables of any size.
The code for the SQLite to Json exporter is below. For an importer using Rapidjson, I can imagine this can be done fairly simple and efficiently (SAX parsing mode) with a custom "filter" handler. For example, it should be possible to keep track of when an object begins and ends, collect all values as variant values with json type info, and write out each complete object with proper types and using a prepared statement. Regards Ben ---- SQLite to Json converter class ---- #include "sqlite_to_json.hpp" #include "rapidjson/filereadstream.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" #include "rapidjson/document.h" #include <stdio.h> #include <iostream> #include <string> #include <vector> extern "C" { #include "sqlite3.h" } using namespace hdm::sqlitejson; using namespace rapidjson; bool SqliteToJson::sqliteQueryToJson(std::string dbPath, std::string sql, std::string jsonFile) { // open the sqlite db at dbPath if (!dbPath.length()) { std::cout << "No db path provided\n"; return false; } sqlite3 *db = NULL; int error = sqlite3_open_v2(dbPath.c_str(), &db, SQLITE_OPEN_READONLY, NULL); if (error != SQLITE_OK) { std::cout << "Failed to open db at path" << dbPath << "\n"; return false; } // prepare the sql statement sqlite3_stmt* readStmt = NULL; error = sqlite3_prepare_v2(db, sql.c_str(), -1, &readStmt, NULL); if (error != SQLITE_OK) { const char *errMsg = sqlite3_errmsg(db); std::cout << "SQL error: " << errMsg << "\n"; return false; } // get the column names std::vector<std::string> columnNames; int count = sqlite3_column_count(readStmt); for (int i=0; i<count; i++) { const char *colName = sqlite3_column_name(readStmt, i); if (colName) { std::string colStr(colName); columnNames.push_back(colName); } } rapidjson::GenericStringBuffer<rapidjson::UTF8< > > jsonBuffer; rapidjson::Writer<rapidjson::StringBuffer> jsonWriter(jsonBuffer); jsonWriter.StartArray(); int numRecs = 0; int rc; while ((rc = sqlite3_step(readStmt)) == SQLITE_ROW) { numRecs++; jsonWriter.StartObject(); for (int colIdx=0; colIdx<columnNames.size(); colIdx++) { std::string columnName = columnNames[colIdx]; jsonWriter.String(columnName.c_str()); // write the column according to data affinity sqlite3_value *val = sqlite3_column_value(readStmt, colIdx); switch (int type = sqlite3_value_type(val)) { case SQLITE_INTEGER: { int64_t val = sqlite3_column_int64(readStmt, colIdx); jsonWriter.Int64(val); break; } case SQLITE_TEXT: { const unsigned char *val = sqlite3_column_text(readStmt, colIdx); if (val) { jsonWriter.String((const char*)val); } else { jsonWriter.Null(); } break; } case SQLITE_FLOAT: { double val = sqlite3_column_double(readStmt, colIdx); jsonWriter.Double(val); break; } case SQLITE_BLOB: { jsonWriter.String("<blob>"); break; } case SQLITE_NULL: { jsonWriter.Null(); break; } default: { assert(false); } } } jsonWriter.EndObject(); } jsonWriter.EndArray(); // write to json FILE* file = fopen(jsonFile.c_str(), "wt"); if (!file) { std::cout << "Failed to write to file " << jsonFile.c_str() << std::endl; return false; } std::cout << "Wrote " << numRecs << " records to file" << jsonFile.c_str() << std::endl; fputs(jsonBuffer.GetString(), file); fclose(file); return true; } Am 21.01.18, 06:55 schrieb "sqlite-users im Auftrag von Simon Slavin" <sqlite-users-boun...@mailinglists.sqlite.org im Auftrag von slav...@bigfraud.org>: Feature request for the Shell Tool: ".mode json". Output should be as a JSON array of objects, with one object for each row of the table. Output should start with the "[" character and end with "]". Rows should be separated with ",\n". Quotes in strings should be escaped for JSON, with a leading backslash. NULL should be supported as the four lower-case characters "null", ignoring ".nullvalue". The above setting should also affect the ".import filename [table]" command as described in section 8 of <https://sqlite.org/cli.html> . Columns should be created as necessary. Signed zeros should be imported as zero. The above facilities should be implemented whether or not DSQLITE_ENABLE_JSON1 was enabled when compiling the shell tool. They are for export and import, not for handling JSON within SQLite. Implementation questions: I am not sure what the program should do if asked to import a value which is an array or object. Perhaps, for compatibility with the JSON1 extension, those should be imported as a string. I am not sure whether the program should respect the settings for ".separator" for JSON mode, either for output or .import. I am not sure how BLOBs should be handled, either for output or .import. Simon. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users