Refactor JSON attribute parsing in rest (#97526)
* Refactor JSON attribute parsing in rest * Early return
This commit is contained in:
parent
832a8247de
commit
c62081430b
2 changed files with 44 additions and 28 deletions
|
@ -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"
|
||||
self._attr_extra_state_attributes = parse_json_attributes(
|
||||
value, self._json_attrs, self._json_attrs_path
|
||||
)
|
||||
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")
|
||||
|
||||
raw_value = value
|
||||
|
||||
|
|
40
homeassistant/components/rest/util.py
Normal file
40
homeassistant/components/rest/util.py
Normal 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 {}
|
Loading…
Add table
Add a link
Reference in a new issue