diff --git a/index.js b/index.js index 521962b..f21bed5 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,9 @@ var jsonld = require("jsonld") , uuid = require("uuid") - , IRI = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i + , IRI = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i , RDFTYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + , XSDTYPE = "http://www.w3.org/2001/XMLSchema#" , async = require("async") , blanksRegexp = /^_:b\d+$/ , genActionStream; @@ -43,6 +44,12 @@ function levelgraphJSONLD(db, jsonldOpts) { } value = blanks[value]; } + // preserve object data type if other then string + if(key === "object" && triple.object.datatype && triple.object.datatype.match(XSDTYPE)){ + if(triple.object.datatype !== "http://www.w3.org/2001/XMLSchema#string"){ + value = '"' + triple.object.value + '"^^<' + triple.object.datatype + '>'; + } + } acc[key] = value; return acc; }, {}); @@ -141,6 +148,29 @@ function levelgraphJSONLD(db, jsonldOpts) { } else if (triple.object.indexOf("_:") !== 0) { acc[triple.subject][triple.predicate] = {}; key = (triple.object.match(IRI)) ? "@id" : "@value"; + // coerce + var coercionCheck = triple.object.match(/"(.*)"\^\^/); + if (coercionCheck) { + switch (coercionCheck[2]) { + case "boolean": + if (coercionCheck[1] === "true") { + triple.object = true; + } + if (coercionCheck[1] === "false") { + triple.object = false; + } + break; + case "integer": + triple.object = parseInt(coercionCheck[1], 10); + break; + case "double": + triple.object = parseFloat(coercionCheck[1]); + break; + case "string": + triple.object = coercionCheck[1]; + break; + } + } acc[triple.subject][triple.predicate][key] = triple.object; cb(null, acc); } else { diff --git a/test/datatype_spec.js b/test/datatype_spec.js new file mode 100644 index 0000000..614878c --- /dev/null +++ b/test/datatype_spec.js @@ -0,0 +1,244 @@ +// http://json-ld.org/spec/latest/json-ld-api/#data-round-tripping + +var level = require("level-test")() + , graph = require("levelgraph") + , jsonld = require("../"); + +describe("jsonld.put data type", function() { + + var db, bbb; + + beforeEach(function() { + db = jsonld(graph(level())); + bbb = fixture("bigbuckbunny.json"); + }); + + describe("coerce", function() { + + it("preserves boolean true", function(done) { + bbb.isFamilyFriendly = true; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/isFamilyFriendly" + }, function(err, triples) { + expect(triples[0].object).to.equal('"true"^^'); + done(); + }); + }); + }); + + it("preserves boolean false", function(done) { + bbb.isFamilyFriendly = false; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/isFamilyFriendly" + }, function(err, triples) { + expect(triples[0].object).to.equal('"false"^^'); + done(); + }); + }); + }); + + it("preserves integer positive", function(done) { + bbb.version = 2; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/version" + }, function(err, triples) { + expect(triples[0].object).to.equal('"2"^^'); + done(); + }); + }); + }); + + it("preserves integer negative", function(done) { + bbb.version = -2; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/version" + }, function(err, triples) { + expect(triples[0].object).to.equal('"-2"^^'); + done(); + }); + }); + }); + + it("preserves integer zero", function(done) { + bbb.version = 0; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/version" + }, function(err, triples) { + expect(triples[0].object).to.equal('"0"^^'); + done(); + }); + }); + }); + + it("preserves double positive", function(done) { + bbb.version = 12.345; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/version" + }, function(err, triples) { + expect(triples[0].object).to.equal('"1.2345E1"^^'); + done(); + }); + }); + }); + + it("preserves double positive", function(done) { + bbb.version = -12.345; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/version" + }, function(err, triples) { + expect(triples[0].object).to.equal('"-1.2345E1"^^'); + done(); + }); + }); + }); + + it("doesn't preserve string", function(done) { + bbb.contentRating = "MPAA PG-13"; + db.jsonld.put(bbb, function() { + db.get({ + predicate: "http://schema.org/contentRating" + }, function(err, triples) { + expect(triples[0].object).to.equal("MPAA PG-13"); + done(); + }); + }); + }); + }); +}); +describe("jsonld.get data type", function() { + + var db, bbb, triple; + + beforeEach(function() { + db = jsonld(graph(level())); + bbb = fixture("bigbuckbunny.json"); + triple = { + subject: bbb["@id"], + predicate: null, + object: null + }; + }); + + describe("coerce", function() { + + it("preserves boolean true", function(done) { + triple.predicate = "http://schema.org/isFamilyFriendly"; + triple.object = '"true"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["isFamilyFriendly"]).to.be.true; + done(); + }); + }); + }); + }); + + it("preserves boolean false", function(done) { + triple.predicate = "http://schema.org/isFamilyFriendly"; + triple.object = '"false"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["isFamilyFriendly"]).to.be.false; + done(); + }); + }); + }); + }); + + it("preserves integer positive", function(done) { + triple.predicate = "http://schema.org/version"; + triple.object = '"2"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["version"]).to.equal(2); + done(); + }); + }); + }); + }); + + it("preserves integer positive", function(done) { + triple.predicate = "http://schema.org/version"; + triple.object = '"-2"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["version"]).to.equal(-2); + done(); + }); + }); + }); + }); + + it("preserves integer zero", function(done) { + triple.predicate = "http://schema.org/version"; + triple.object = '"0"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["version"]).to.equal(0); + done(); + }); + }); + }); + }); + + it("preserves double positive", function(done) { + triple.predicate = "http://schema.org/version"; + triple.object = '"1.2345E1"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["version"]).to.equal(12.345); + done(); + }); + }); + }); + }); + + it("preserves double negative", function(done) { + triple.predicate = "http://schema.org/version"; + triple.object = '"-1.2345E1"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["version"]).to.equal(-12.345); + done(); + }); + }); + }); + }); + + it("does not preserve string", function(done) { + triple.predicate = "http://schema.org/contentRating"; + triple.object = '"MPAA PG-13"^^'; + + db.jsonld.put(bbb, function() { + db.put(triple, function() { + db.jsonld.get(bbb["@id"], bbb["@context"], function(err, doc) { + expect(doc["contentRating"]).to.equal("MPAA PG-13"); + done(); + }); + }); + }); + }); + + }); +}); diff --git a/test/fixture/bigbuckbunny.json b/test/fixture/bigbuckbunny.json new file mode 100644 index 0000000..cb6c321 --- /dev/null +++ b/test/fixture/bigbuckbunny.json @@ -0,0 +1,7 @@ +{ + "@context": { + "@vocab": "http://schema.org/" + }, + "@id": "http://www.bigbuckbunny.org/", + "name": "Big Buck Bunny" +} diff --git a/test/put_spec.js b/test/put_spec.js index 1560677..434bdaa 100644 --- a/test/put_spec.js +++ b/test/put_spec.js @@ -135,7 +135,7 @@ describe("jsonld.put", function() { db.get({ subject: "http://manu.sporny.org#person" , predicate: "http://xmlns.com/foaf/0.1/age" - , object: 42 + , object: '"42"^^' }, function(err, triples) { expect(triples).to.have.length(1); done();