From 46f0b33bc8ff57b44a8c52cdb8224e141b8476e4 Mon Sep 17 00:00:00 2001 From: Young Hahn Date: Fri, 12 Jul 2013 05:41:31 -0400 Subject: [PATCH] Add support for nested json metadata. --- lib/mbtiles.js | 24 +++++++++++++++++++++++- test/fixtures/plain_1.mbtiles | Bin 561152 -> 561152 bytes test/info.test.js | 15 +++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/mbtiles.js b/lib/mbtiles.js index 4de9f71..689e71d 100644 --- a/lib/mbtiles.js +++ b/lib/mbtiles.js @@ -229,6 +229,18 @@ MBTiles.prototype.getInfo = function(callback) { if (err && err.errno !== 1) return callback(err); if (rows) rows.forEach(function(row) { switch (row.name) { + // The special "json" key/value pair allows JSON to be serialized + // and merged into the metadata of an MBTiles based source. This + // enables nested properties and non-string datatypes to be + // captured by the MBTiles metadata table. + case 'json': + try { var jsondata = JSON.parse(row.value); } + catch (err) { return callback(err); } + Object.keys(jsondata).reduce(function(memo, key) { + memo[key] = memo[key] || jsondata[key]; + return memo; + }, info); + break; case 'minzoom': case 'maxzoom': info[row.name] = parseInt(row.value, 10); @@ -537,11 +549,21 @@ MBTiles.prototype.putInfo = function(data, callback) { if (!this.open) return callback(new Error('MBTiles not yet loaded')); if (!this._isWritable) return callback(new Error('MBTiles not in write mode')); + var jsondata; var stmt = this._db.prepare('REPLACE INTO metadata (name, value) VALUES (?, ?)'); stmt.on('error', callback); for (var key in data) { - stmt.run(key, String(data[key])); + // If a data property is a javascript hash/object, slip it into + // the 'json' field which contains stringified JSON to be merged + // in at read time. Allows nested/deep metadata to be recorded. + if (typeof data[key] === 'object' && !Array.isArray(data[key])) { + jsondata = jsondata || {}; + jsondata[key] = data[key]; + } else { + stmt.run(key, String(data[key])); + } } + if (jsondata) stmt.run('json', JSON.stringify(jsondata)); var mbtiles = this; stmt.finalize(function(err) { diff --git a/test/fixtures/plain_1.mbtiles b/test/fixtures/plain_1.mbtiles index 2ca86459d6e12d3d3a52ca2b913f612c5918a89e..5fdce657e67fc1d17d21cabb1017f6db13d0a767 100644 GIT binary patch delta 177 zcmZozpwzHHX@WFk`$QRM)^-NnM~WL$7KjV6GxIYre_+1HypMS;^L%D6X8z5J5`R!ps10afu4a< z?Pf3OT{1lE%o`Y(zcN2%zRtX1GoQr*W=;-fQAUu7?9Dr^+jm+s0x=U1GXpUT5VHa? O8xXT^-)YU^9s&SxIyqJV delta 106 zcmZozpwzHHX@WFk+e8^>);0#+N3t7J7KjV5F?%sEe_+1HypMS;^L%En&4LuE6`TAx7iv`RR1Gt-aTDR}CW&~m;AZ7+)79eH?Vm2UV-@enD!#xB5 DO>iV4 diff --git a/test/info.test.js b/test/info.test.js index c88c7fa..edee2ce 100644 --- a/test/info.test.js +++ b/test/info.test.js @@ -30,7 +30,8 @@ describe('info', function() { formatter: null, center: [ 0, 7.500000001278025, 2 ], bounds: [ -179.9999999749438, -69.99999999526695, 179.9999999749438, 84.99999999782301 ], - + // Test that json data is merged in. + level1: { level2: 'property' }, // These aren't part of TileJSON, but exist in an MBTiles file. filesize: 561152, type: 'baselayer', @@ -45,6 +46,11 @@ describe('info', function() { it('get/put metadata from empty file', function(done) { this.timeout(10e3); + var info = { + version: '1.0.0', + level1: { level2: 'property' } + }; + new MBTiles(fixtures.empty, function(err, mbtiles) { assert.ifError(err); @@ -58,14 +64,14 @@ describe('info', function() { scheme: "tms" }, data); - mbtiles.putInfo({ version: '1.0.0' }, function(err) { + mbtiles.putInfo(info, function(err) { assert.ok(err); assert.equal(err.message, 'MBTiles not in write mode'); mbtiles.startWriting(function(err) { assert.ifError(err); - mbtiles.putInfo({ version: '1.0.0' }, function(err) { + mbtiles.putInfo(info, function(err) { assert.ifError(err); mbtiles.stopWriting(function(err) { @@ -79,7 +85,8 @@ describe('info', function() { filesize: 0, id: "empty", scheme: "tms", - version: "1.0.0" + version: "1.0.0", + level1: { level2: "property" }, }, data); done();