diff --git a/nodes/core/locales/en-US/messages.json b/nodes/core/locales/en-US/messages.json index 74ec0bcd4..c3586d412 100644 --- a/nodes/core/locales/en-US/messages.json +++ b/nodes/core/locales/en-US/messages.json @@ -697,7 +697,9 @@ "errors": { "dropped-object": "Ignored non-object payload", "dropped": "Ignored unsupported payload type", - "dropped-error": "Failed to convert payload" + "dropped-error": "Failed to convert payload", + "schema-error": "JSON Schema error", + "schema-error-compile": "JSON Schema error: failed to compile schema" }, "label": { "o2j": "Object to JSON options", diff --git a/nodes/core/parsers/70-JSON.html b/nodes/core/parsers/70-JSON.html index 565bae9a0..a440e5d45 100644 --- a/nodes/core/parsers/70-JSON.html +++ b/nodes/core/parsers/70-JSON.html @@ -31,6 +31,8 @@
schemaError
property
+ containing an array of errors.By default, the node operates on msg.payload
, but can be configured
diff --git a/nodes/core/parsers/70-JSON.js b/nodes/core/parsers/70-JSON.js
index ce547fe10..eb0bec63c 100644
--- a/nodes/core/parsers/70-JSON.js
+++ b/nodes/core/parsers/70-JSON.js
@@ -32,24 +32,19 @@ module.exports = function(RED) {
this.on("input", function(msg) {
var validate = false;
if (msg.schema) {
- if (typeof msg.schema === "object") {
- // If input schema is different, re-compile it
- if (JSON.stringify(this.schema) != JSON.stringify(msg.schema)) {
- node.warn('Schema different, compiling');
- try {
- this.compiledSchema = ajv.compile(msg.schema);
- this.schema = msg.schema;
- } catch(e) {
- this.schema = null;
- this.compiledSchema = null;
- node.error("JSON Schema error: failed to compile schema", msg);
- return;
- }
+ // If input schema is different, re-compile it
+ if (JSON.stringify(this.schema) != JSON.stringify(msg.schema)) {
+ try {
+ this.compiledSchema = ajv.compile(msg.schema);
+ this.schema = msg.schema;
+ } catch(e) {
+ this.schema = null;
+ this.compiledSchema = null;
+ node.error(RED._("json.errors.schema-error-compile"), msg);
+ return;
}
- validate = true;
- } else {
- node.warn("Schema present but not an object, ignoring schema");
}
+ validate = true;
}
var value = RED.util.getMessageProperty(msg,node.property);
if (value !== undefined) {
@@ -62,7 +57,7 @@ module.exports = function(RED) {
node.send(msg);
} else {
msg.schemaError = this.compiledSchema.errors;
- node.error(`JSON Schema error: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
+ node.error(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
}
} else {
node.send(msg);
@@ -83,7 +78,7 @@ module.exports = function(RED) {
node.send(msg);
} else {
msg.schemaError = this.compiledSchema.errors;
- node.error(`JSON Schema error: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
+ node.error(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
}
} else {
RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
diff --git a/test/nodes/core/parsers/70-JSON_spec.js b/test/nodes/core/parsers/70-JSON_spec.js
index 28fffde85..ba913b1e7 100644
--- a/test/nodes/core/parsers/70-JSON_spec.js
+++ b/test/nodes/core/parsers/70-JSON_spec.js
@@ -247,4 +247,85 @@ describe('JSON node', function() {
});
});
});
+
+ it('should pass an object if provided a valid JSON string and schema', function(done) {
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ jn2.on("input", function(msg) {
+ should.equal(msg.payload.number, 3);
+ should.equal(msg.payload.string, "allo");
+ done();
+ });
+ var jsonString = '{"number": 3, "string": "allo"}';
+ var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
+ jn1.receive({payload:jsonString, schema:schema});
+ });
+ });
+
+ it('should pass a string if provided a valid object and schema', function(done) {
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ jn2.on("input", function(msg) {
+ should.equal(msg.payload, '{"number":3,"string":"allo"}');
+ done();
+ });
+ var obj = {"number": 3, "string": "allo"};
+ var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
+ jn1.receive({payload:obj, schema:schema});
+ });
+ });
+
+ it('should log an error if passed an invalid object and valid schema', function(done) {
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ try {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
+ var obj = {"number": "foo", "string": 3};
+ jn1.receive({payload:obj, schema:schema});
+ var logEvents = helper.log().args.filter(function(evt) {
+ return evt[0].type == "json";
+ });
+ logEvents.should.have.length(1);
+ logEvents[0][0].should.have.a.property('msg');
+ logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
+ logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
+ done();
+ } catch(err) {
+ done(err);
+ }
+ });
+ });
+
+ it('should log an error if passed a valid object and invalid schema', function(done) {
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ try {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ var schema = "garbage";
+ var obj = {"number": "foo", "string": 3};
+ jn1.receive({payload:obj, schema:schema});
+ var logEvents = helper.log().args.filter(function(evt) {
+ return evt[0].type == "json";
+ });
+ logEvents.should.have.length(1);
+ logEvents[0][0].should.have.a.property('msg');
+ logEvents[0][0].msg.should.equal("json.errors.schema-error-compile");
+ logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
+ done();
+ } catch(err) {
+ done(err);
+ }
+ });
+ });
});