By default, the node operates on msg.payload, but can be configured
+ to convert any message property.
+
The node can also be configured to ensure a particular encoding instead of toggling
+ between the two. This can be used, for example, with the HTTP In
+ node to ensure the payload is a parsed object even if an incoming request
+ did not set its content-type correctly for the HTTP In node to do the conversion.
+
diff --git a/nodes/core/parsers/70-JSON.js b/nodes/core/parsers/70-JSON.js
index 5709e8f57..aed328574 100644
--- a/nodes/core/parsers/70-JSON.js
+++ b/nodes/core/parsers/70-JSON.js
@@ -20,29 +20,40 @@ module.exports = function(RED) {
function JSONNode(n) {
RED.nodes.createNode(this,n);
this.indent = n.pretty ? 4 : 0;
+ this.action = n.action||"";
+ this.property = n.property||"payload";
var node = this;
this.on("input", function(msg) {
- if (msg.hasOwnProperty("payload")) {
- if (typeof msg.payload === "string") {
- try {
- msg.payload = JSON.parse(msg.payload);
- node.send(msg);
- }
- catch(e) { node.error(e.message,msg); }
- }
- else if (typeof msg.payload === "object") {
- if (!Buffer.isBuffer(msg.payload)) {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ if (typeof value === "string") {
+ if (node.action === "" || node.action === "obj") {
try {
- msg.payload = JSON.stringify(msg.payload,null,node.indent);
+ RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
node.send(msg);
}
- catch(e) { node.error(RED._("json.errors.dropped-error")); }
+ catch(e) { node.error(e.message,msg); }
+ } else {
+ node.send(msg);
+ }
+ }
+ else if (typeof value === "object") {
+ if (node.action === "" || node.action === "str") {
+ if (!Buffer.isBuffer(value)) {
+ try {
+ RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
+ node.send(msg);
+ }
+ catch(e) { node.error(RED._("json.errors.dropped-error")); }
+ }
+ else { node.warn(RED._("json.errors.dropped-object")); }
+ } else {
+ node.send(msg);
}
- else { node.warn(RED._("json.errors.dropped-object")); }
}
else { node.warn(RED._("json.errors.dropped")); }
}
- else { node.send(msg); } // If no payload - just pass it on.
+ else { node.send(msg); } // If no property - just pass it on.
});
}
RED.nodes.registerType("json",JSONNode);
diff --git a/test/nodes/core/parsers/70-JSON_spec.js b/test/nodes/core/parsers/70-JSON_spec.js
index 6d3d857f3..833d118e1 100644
--- a/test/nodes/core/parsers/70-JSON_spec.js
+++ b/test/nodes/core/parsers/70-JSON_spec.js
@@ -28,17 +28,8 @@ describe('JSON node', function() {
helper.unload();
});
- it('should be loaded', function(done) {
- var flow = [{id:"jsonNode1", type:"json", name: "jsonNode" }];
- helper.load(jsonNode, flow, function() {
- var jsonNode1 = helper.getNode("jsonNode1");
- jsonNode1.should.have.property('name', 'jsonNode');
- done();
- });
- });
-
it('should convert a valid json string to a javascript object', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -56,7 +47,7 @@ describe('JSON node', function() {
});
it('should convert a javascript object to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -71,7 +62,7 @@ describe('JSON node', function() {
});
it('should convert a array to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -86,7 +77,7 @@ describe('JSON node', function() {
});
it('should log an error if asked to parse an invalid json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
try {
@@ -108,7 +99,7 @@ describe('JSON node', function() {
});
it('should log an error if asked to parse something thats not json or js', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -137,7 +128,7 @@ describe('JSON node', function() {
});
it('should pass straight through if no payload set', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"},
+ var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
{id:"jn2", type:"helper"}];
helper.load(jsonNode, flow, function() {
var jn1 = helper.getNode("jn1");
@@ -151,4 +142,105 @@ describe('JSON node', function() {
});
});
+ it('should ensure the result is a json string', function(done) {
+ var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ var count = 0;
+ jn2.on("input", function(msg) {
+ try {
+ should.equal(msg.payload, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
+ count++;
+ if (count === 2) {
+ done();
+ }
+ } catch(err) {
+ done(err);
+ }
+ });
+ var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
+ jn1.receive({payload:obj,topic: "bar"});
+ jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
+ });
+ });
+
+ it('should ensure the result is a JS Object', function(done) {
+ var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
+ {id:"jn2", type:"helper"}];
+ helper.load(jsonNode, flow, function() {
+ var jn1 = helper.getNode("jn1");
+ var jn2 = helper.getNode("jn2");
+ var count = 0;
+ jn2.on("input", function(msg) {
+ try {
+ msg.should.have.property('topic', 'bar');
+ msg.payload.should.have.property('employees');
+ msg.payload.employees[0].should.have.property('firstName', 'John');
+ msg.payload.employees[0].should.have.property('lastName', 'Smith');
+ count++;
+ if (count === 2) {
+ done();
+ }
+ } catch(err) {
+ done(err);
+ }
+ });
+ var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
+ jn1.receive({payload:obj,topic: "bar"});
+ jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
+ });
+ });
+
+ it('should handle any msg property - receive existing string', function(done) {
+ var flow = [{id:"jn1",type:"json",property:"one.two",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) {
+ try {
+ msg.should.have.property('topic', 'bar');
+ msg.should.have.property('one');
+ msg.one.should.have.property('two');
+ msg.one.two.should.have.property('employees');
+ msg.one.two.employees[0].should.have.property('firstName', 'John');
+ msg.one.two.employees[0].should.have.property('lastName', 'Smith');
+ done();
+ } catch(err) {
+ done(err);
+ }
+ });
+ var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
+ jn1.receive({payload:"",one:{two:jsonString},topic: "bar"});
+
+ var logEvents = helper.log().args.filter(function(evt) {
+ return evt[0].type == "json";
+ });
+ });
+ });
+
+ it('should handle any msg property - receive existing obj', function(done) {
+ var flow = [{id:"jn1",type:"json",property:"one.two",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) {
+ try {
+ should.equal(msg.one.two, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
+ done();
+ } catch(err) {
+ done(err);
+ }
+ });
+ var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
+ jn1.receive({payload:"",one:{two:JSON.parse(jsonString)},topic: "bar"});
+
+ var logEvents = helper.log().args.filter(function(evt) {
+ return evt[0].type == "json";
+ });
+ });
+ });
});