HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Node.js JSON searching & updating

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
jsonnodeupdatingsearching

Problem

I'm working on a web-based on/off controller for multiple switches. I'm looking for a good way to manage the current state of a switch and updating the current state on change.

So far I've got a lib.json file which looks like this:

{   
    "Lights":[{
        "name": "light-one",
        "pin":"3",
        "command":"gpioDo",
        "actions": {
            "on":"1",
            "off":"0"
        }
    },{
        "name": "light-two",
        "pin":"5",
        "command":"gpioDo",
        "actions": {
            "on":"1",
            "off":"0"
        }
    },{
        "name": "light-three",
        "pin":"7",
        "command":"gpioDo",
        "actions": {
            "on":"1",
            "off":"0"
        }
    }],
    "Locks":[{
        "name": "lock-one",
        "pin":"8",
        "command":"gpioDo",
        "actions": {
            "on":"1",
            "off":"0"
        }
    },{
        "name": "lock-two",
        "pin":"12",
        "command":"gpioDo",
        "actions": {
            "on":"1",
            "off":"0"
        }
    }]
}


A web-page is dynamically created using some jQuery and appropriate groups of buttons are created according to the lib.json.

On the server I take that lib.json file and create a state object via this little snippet (note that on initial run all states must be off):

var state = [];
var lib = JSON.parse(fs.readFileSync('lib.json', 'utf8'));
...
for (i in lib) {
  for (x in lib[i]){
    state.push({pin:lib[i][x].pin, val:0});
  }
}


which produces:

[ { pin: '5', val: 0 },
  { pin: '7', val: 0 },
  { pin: '8', val: 0 },
  { pin: '12', val: 0 } ]


When a web-page button is pushed, the server receives a string containing misc elements of the lib.json referencing a command with parameters to perform.

It also updates the state object to represent the change with an updateVal() command.

```
function updateVal(pinId, valId){
var i;
for (i = 0; i < state.length; ++i) {
if (state[

Solution

A few things to consider;

Is it worth abstracting the collection into the lights and locks arrays? The data format is effectively identical, and I think separating them makes the collection as a whole harder to iterate over.

To follow up from the first point, I try to avoid for loops in JavaScript because there's so many efficient and readable alternatives for working with arrays. If we were to rewrite your data structure to be the following:

{
    "switches": [{
        "name": "light-one",
        "pin": 3, // definitely store integers as ints and not wrapped in quotes!
        "command":"gpioDo",
        "actions": {
            "on": 1,
            "off": 0
        }
    }, {
        // ...
    }]
}


We can then rewrite your first example to be the following:

var state = lib.map(function(switch) {
    return {
        pin: switch.pin,
        val: 0
    };
});


This removes the index variables completely, and in my opinion makes the code more readable. In the case of not rewriting the data structure you could just iterate over the lights and locks arrays with a map function, then concat them together.

In the same way we can iterate over this when you want to set the values.

var updateVal = function(pinID, valID) {
    state.forEach(function(s) {
        s.pin === pinID && (s.val = valID);
    });
};


The function expression is just a personal preference, but I like it as it forces you to declare a function before using it.

I'm also not sure if the actions key needs to be like it is; perhaps you need it for other entities that have other actions, but I would probably replace it with a boolean active (to represent on and off), for simplicity.

Hope this helps. :)

Code Snippets

{
    "switches": [{
        "name": "light-one",
        "pin": 3, // definitely store integers as ints and not wrapped in quotes!
        "command":"gpioDo",
        "actions": {
            "on": 1,
            "off": 0
        }
    }, {
        // ...
    }]
}
var state = lib.map(function(switch) {
    return {
        pin: switch.pin,
        val: 0
    };
});
var updateVal = function(pinID, valID) {
    state.forEach(function(s) {
        s.pin === pinID && (s.val = valID);
    });
};

Context

StackExchange Code Review Q#59669, answer score: 3

Revisions (0)

No revisions yet.