Refactor JSON attribute parsing in rest (#97526)

* Refactor JSON attribute parsing in rest

* Early return
This commit is contained in:
epenet 2023-08-11 11:00:55 +02:00 committed by GitHub
parent 832a8247de
commit c62081430b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 28 deletions

View file

@ -5,7 +5,6 @@ import logging
import ssl
from typing import Any
from jsonpath import jsonpath
import voluptuous as vol
from homeassistant.components.sensor import (
@ -39,13 +38,13 @@ from homeassistant.helpers.template_entity import (
)
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.util.json import json_loads
from . import async_get_config_and_coordinator, create_rest_data_from_config
from .const import CONF_JSON_ATTRS, CONF_JSON_ATTRS_PATH, DEFAULT_SENSOR_NAME
from .data import RestData
from .entity import RestEntity
from .schema import RESOURCE_SCHEMA, SENSOR_SCHEMA
from .util import parse_json_attributes
_LOGGER = logging.getLogger(__name__)
@ -163,32 +162,9 @@ class RestSensor(ManualTriggerSensorEntity, RestEntity, SensorEntity):
value = self.rest.data_without_xml()
if self._json_attrs:
if value:
try:
json_dict = json_loads(value)
if self._json_attrs_path is not None:
json_dict = jsonpath(json_dict, self._json_attrs_path)
# jsonpath will always store the result in json_dict[0]
# so the next line happens to work exactly as needed to
# find the result
if isinstance(json_dict, list):
json_dict = json_dict[0]
if isinstance(json_dict, dict):
attrs = {
k: json_dict[k] for k in self._json_attrs if k in json_dict
}
self._attr_extra_state_attributes = attrs
else:
_LOGGER.warning(
"JSON result was not a dictionary"
" or list with 0th element a dictionary"
)
except ValueError:
_LOGGER.warning("REST result could not be parsed as JSON")
_LOGGER.debug("Erroneous JSON: %s", value)
else:
_LOGGER.warning("Empty reply found when expecting JSON data")
self._attr_extra_state_attributes = parse_json_attributes(
value, self._json_attrs, self._json_attrs_path
)
raw_value = value

View file

@ -0,0 +1,40 @@
"""Helpers for RESTful API."""
import logging
from typing import Any
from jsonpath import jsonpath
from homeassistant.util.json import json_loads
_LOGGER = logging.getLogger(__name__)
def parse_json_attributes(
value: str | None, json_attrs: list[str], json_attrs_path: str | None
) -> dict[str, Any]:
"""Parse JSON attributes."""
if not value:
_LOGGER.warning("Empty reply found when expecting JSON data")
return {}
try:
json_dict = json_loads(value)
if json_attrs_path is not None:
json_dict = jsonpath(json_dict, json_attrs_path)
# jsonpath will always store the result in json_dict[0]
# so the next line happens to work exactly as needed to
# find the result
if isinstance(json_dict, list):
json_dict = json_dict[0]
if isinstance(json_dict, dict):
return {k: json_dict[k] for k in json_attrs if k in json_dict}
_LOGGER.warning(
"JSON result was not a dictionary or list with 0th element a dictionary"
)
except ValueError:
_LOGGER.warning("REST result could not be parsed as JSON")
_LOGGER.debug("Erroneous JSON: %s", value)
return {}