Parsing a value from JSON response that keeps changing order

440 views Asked by At

Im trying to parse JSON response from my home automation system in javscript. The response is available here

That is only a small part of the response, also, the order of keys changes on every reboot for reasons i do not know, su using the the number index wont really work i need to be able to store the state value of sensor.out, sensor.in, sensor.door into variables for tasker on andorid i tried to select using the entity.id, but for some reason the code never finished ( i believe i just didnt know what i was doing)

3

There are 3 answers

0
trincot On BEST ANSWER

With ES6 you can use the Array#find method:

response.find(o => o.entity_id == 'sensor.out').state

See snippet:

var response = [ { "attributes":{ "friendly_name":"door" }, "entity_id":"sensor.door", "last_changed":"2016-12-31T11:15:59.395808+00:00", "last_updated":"2016-12-31T11:15:59.395808+00:00", "state":"closed" }, { "attributes":{ "friendly_name":"In", "unit_of_measurement":"\u00b0C" }, "entity_id":"sensor.in", "last_changed":"2016-12-31T11:20:02.179821+00:00", "last_updated":"2016-12-31T11:20:02.179821+00:00", "state":"20.7" }, { "attributes":{ "changed_by":null, "code_format":".+", "friendly_name":"panel" }, "entity_id":"alarm_control_panel.panel", "last_changed":"2016-12-31T11:14:56.471966+00:00", "last_updated":"2016-12-31T11:14:56.471966+00:00", "state":"disarmed" }, { "attributes":{ "friendly_name":"Out", "unit_of_measurement":"\u00b0C" }, "entity_id":"sensor.out", "last_changed":"2016-12-31T11:14:58.452345+00:00", "last_updated":"2016-12-31T11:14:58.452345+00:00", "state":"7.1" }];
var state = response.find(o => o.entity_id == 'sensor.out').state;
console.log('sensor.out state is', state);

Alternatively, you could convert the response to an object with the entity id values as keys, so you can access it like response['session.out'].state:

response = Object.assign({}, ...response.map( o => ({[o.entity_id]: o}) ));

See snippet:

var response = [ { "attributes":{ "friendly_name":"door" }, "entity_id":"sensor.door", "last_changed":"2016-12-31T11:15:59.395808+00:00", "last_updated":"2016-12-31T11:15:59.395808+00:00", "state":"closed" }, { "attributes":{ "friendly_name":"In", "unit_of_measurement":"\u00b0C" }, "entity_id":"sensor.in", "last_changed":"2016-12-31T11:20:02.179821+00:00", "last_updated":"2016-12-31T11:20:02.179821+00:00", "state":"20.7" }, { "attributes":{ "changed_by":null, "code_format":".+", "friendly_name":"panel" }, "entity_id":"alarm_control_panel.panel", "last_changed":"2016-12-31T11:14:56.471966+00:00", "last_updated":"2016-12-31T11:14:56.471966+00:00", "state":"disarmed" }, { "attributes":{ "friendly_name":"Out", "unit_of_measurement":"\u00b0C" }, "entity_id":"sensor.out", "last_changed":"2016-12-31T11:14:58.452345+00:00", "last_updated":"2016-12-31T11:14:58.452345+00:00", "state":"7.1" }];
response = Object.assign({}, ...response.map( o => ({[o.entity_id]: o}) ));
console.log('sensor.out state is', response['sensor.out'].state);

5
Tim Consolazio On

If you're trying to uses indexes to select properties from objects, you shouldn't be, unless there is a very specific reason to do so.

Fortunately that's fine, you don't need to know the order. I took two of the objects from your JSON array, scrambled up the properties, and wrote a function that returns any object that contains the key/val you specify.

Your question is a little hard to follow, but I think this will give you the idea.

<script type="text/javascript">
let arr = [
  {
    "attributes":{
      "friendly_name":"door"
    },
    "entity_id":"sensor.frontdoor",
    "last_changed":"2016-12-31T11:15:59.395808+00:00",
    "last_updated":"2016-12-31T11:15:59.395808+00:00",
    "state":"closed"
  },
  {
    "last_changed":"2016-12-31T11:15:59.395808+00:00",
    "state":"closed",
    "attributes":{
      "friendly_name":"door"
    },
    "entity_id":"sensor.backdoor",
    "last_updated":"2016-12-31T11:15:59.395808+00:00"
  }
];

function findKey ( theKey, theVal ) {
  let reduced = arr.filter ( d => {
    return d [ theKey ] === theVal;
  });

  return reduced;
}

let targets = findKey ( 'entity_id', 'sensor.backdoor' );
targets.forEach ( d => {
   // This check is a little naive, but should give you the idea
   if ( 'state' in d ) {
      console.log ( d.state );
   }
} );
</script>
0
Edward D On

What everyone says is correct: The order of keys in the response doesn't matter. Use the (string) key, not a numerical index.

var arr = [
  {
    "entity_id":"sensor.door",
    "state":"closed"
  }];   // other attributes chopped out for brevity

var entity_id_interested_in = 'sensor.door';
var state = '[entity_id not found in response]';
for (var i = 0; i < arr.length; i++) {

    console.log(arr[i].entity_id + ' state:' + arr[i].state);
    if (arr[i].entity_id == entity_id_interested_in)
    {
       state = arr[i].state;
       break;
    }
}
console.log (state);