diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index 0901a4f63a6..754fcb7ec44 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -2,7 +2,6 @@ from __future__ import annotations import functools -from json import JSONDecodeError, loads as json_loads import logging import voluptuous as vol @@ -29,6 +28,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.json import JSON_DECODE_EXCEPTIONS, json_loads from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import subscription @@ -418,7 +418,7 @@ class MqttCover(MqttEntity, CoverEntity): try: payload = json_loads(payload) - except JSONDecodeError: + except JSON_DECODE_EXCEPTIONS: pass if isinstance(payload, dict): diff --git a/homeassistant/components/mqtt/discovery.py b/homeassistant/components/mqtt/discovery.py index 04dd2d7917f..5b39e8fa1b5 100644 --- a/homeassistant/components/mqtt/discovery.py +++ b/homeassistant/components/mqtt/discovery.py @@ -4,7 +4,6 @@ from __future__ import annotations import asyncio from collections import deque import functools -import json import logging import re import time @@ -17,6 +16,7 @@ from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, async_dispatcher_send, ) +from homeassistant.helpers.json import json_loads from homeassistant.loader import async_get_mqtt from .. import mqtt @@ -117,7 +117,7 @@ async def async_start( # noqa: C901 if payload: try: - payload = json.loads(payload) + payload = json_loads(payload) except ValueError: _LOGGER.warning("Unable to parse JSON %s: '%s'", object_id, payload) return diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index be49f1ad2e3..716366cbe22 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -1,6 +1,5 @@ """Support for MQTT JSON lights.""" from contextlib import suppress -import json import logging import voluptuous as vol @@ -46,6 +45,7 @@ from homeassistant.const import ( ) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.json import json_dumps, json_loads from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.typing import ConfigType import homeassistant.util.color as color_util @@ -317,7 +317,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity): @log_messages(self.hass, self.entity_id) def state_received(msg): """Handle new MQTT messages.""" - values = json.loads(msg.payload) + values = json_loads(msg.payload) if values["state"] == "ON": self._state = True @@ -644,7 +644,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity): await self.async_publish( self._topic[CONF_COMMAND_TOPIC], - json.dumps(message), + json_dumps(message), self._config[CONF_QOS], self._config[CONF_RETAIN], self._config[CONF_ENCODING], @@ -669,7 +669,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity): await self.async_publish( self._topic[CONF_COMMAND_TOPIC], - json.dumps(message), + json_dumps(message), self._config[CONF_QOS], self._config[CONF_RETAIN], self._config[CONF_ENCODING], diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index dcf387eb360..10fe6cb6cc5 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -4,7 +4,6 @@ from __future__ import annotations from abc import abstractmethod import asyncio from collections.abc import Callable -import json import logging from typing import Any, Protocol, cast, final @@ -47,6 +46,7 @@ from homeassistant.helpers.entity import ( async_generate_entity_id, ) from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.json import json_loads from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import debug_info, subscription @@ -393,7 +393,7 @@ class MqttAttributes(Entity): def attributes_message_received(msg: ReceiveMessage) -> None: try: payload = attr_tpl(msg.payload) - json_dict = json.loads(payload) if isinstance(payload, str) else None + json_dict = json_loads(payload) if isinstance(payload, str) else None if isinstance(json_dict, dict): filtered_dict = { k: v diff --git a/homeassistant/components/mqtt/siren.py b/homeassistant/components/mqtt/siren.py index e7b91274f4f..a6cff4cf91d 100644 --- a/homeassistant/components/mqtt/siren.py +++ b/homeassistant/components/mqtt/siren.py @@ -3,7 +3,6 @@ from __future__ import annotations import copy import functools -import json import logging from typing import Any @@ -32,6 +31,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.json import JSON_DECODE_EXCEPTIONS, json_dumps, json_loads from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from . import subscription @@ -253,13 +253,13 @@ class MqttSiren(MqttEntity, SirenEntity): json_payload = {STATE: payload} else: try: - json_payload = json.loads(payload) + json_payload = json_loads(payload) _LOGGER.debug( "JSON payload detected after processing payload '%s' on topic %s", json_payload, msg.topic, ) - except json.decoder.JSONDecodeError: + except JSON_DECODE_EXCEPTIONS: _LOGGER.warning( "No valid (JSON) payload detected after processing payload '%s' on topic %s", json_payload, @@ -344,7 +344,7 @@ class MqttSiren(MqttEntity, SirenEntity): payload = ( self._command_templates[template](value, template_variables) if self._command_templates[template] - else json.dumps(template_variables) + else json_dumps(template_variables) ) if payload and payload not in PAYLOAD_NONE: await self.async_publish( diff --git a/homeassistant/components/mqtt/trigger.py b/homeassistant/components/mqtt/trigger.py index 7d1f93d30eb..aca4cf0a480 100644 --- a/homeassistant/components/mqtt/trigger.py +++ b/homeassistant/components/mqtt/trigger.py @@ -1,6 +1,5 @@ """Offer MQTT listening automation rules.""" from contextlib import suppress -import json import logging import voluptuous as vol @@ -12,6 +11,7 @@ from homeassistant.components.automation import ( from homeassistant.const import CONF_PAYLOAD, CONF_PLATFORM, CONF_VALUE_TEMPLATE from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, callback from homeassistant.helpers import config_validation as cv, template +from homeassistant.helpers.json import json_loads from homeassistant.helpers.typing import ConfigType from .. import mqtt @@ -89,7 +89,7 @@ async def async_attach_trigger( } with suppress(ValueError): - data["payload_json"] = json.loads(mqttmsg.payload) + data["payload_json"] = json_loads(mqttmsg.payload) hass.async_run_hass_job(job, {"trigger": data}) diff --git a/homeassistant/components/mqtt/vacuum/schema_legacy.py b/homeassistant/components/mqtt/vacuum/schema_legacy.py index f25131c43b7..6b957aded5c 100644 --- a/homeassistant/components/mqtt/vacuum/schema_legacy.py +++ b/homeassistant/components/mqtt/vacuum/schema_legacy.py @@ -1,6 +1,4 @@ """Support for Legacy MQTT vacuum.""" -import json - import voluptuous as vol from homeassistant.components.vacuum import ( @@ -14,6 +12,7 @@ from homeassistant.const import ATTR_SUPPORTED_FEATURES, CONF_NAME from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.icon import icon_for_battery_level +from homeassistant.helpers.json import json_dumps from .. import subscription from ..config import MQTT_BASE_SCHEMA @@ -511,7 +510,7 @@ class MqttVacuum(MqttEntity, VacuumEntity): if params: message = {"command": command} message.update(params) - message = json.dumps(message) + message = json_dumps(message) else: message = command await self.async_publish( diff --git a/homeassistant/components/mqtt/vacuum/schema_state.py b/homeassistant/components/mqtt/vacuum/schema_state.py index 3d670780994..af6c8d289d8 100644 --- a/homeassistant/components/mqtt/vacuum/schema_state.py +++ b/homeassistant/components/mqtt/vacuum/schema_state.py @@ -1,6 +1,4 @@ """Support for a State MQTT vacuum.""" -import json - import voluptuous as vol from homeassistant.components.vacuum import ( @@ -21,6 +19,7 @@ from homeassistant.const import ( ) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.json import json_dumps, json_loads from .. import subscription from ..config import MQTT_BASE_SCHEMA @@ -203,7 +202,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity): @log_messages(self.hass, self.entity_id) def state_message_received(msg): """Handle state MQTT message.""" - payload = json.loads(msg.payload) + payload = json_loads(msg.payload) if STATE in payload and ( payload[STATE] in POSSIBLE_STATES or payload[STATE] is None ): @@ -347,7 +346,7 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity): if params: message = {"command": command} message.update(params) - message = json.dumps(message) + message = json_dumps(message) else: message = command await self.async_publish( diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 64733b4f0f7..b930de9b6c3 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -688,7 +688,7 @@ async def test_sending_mqtt_commands_and_optimistic( await common.async_turn_on(hass, "light.test") mqtt_mock.async_publish.assert_called_once_with( - "test_light_rgb/set", '{"state": "ON"}', 2, False + "test_light_rgb/set", '{"state":"ON"}', 2, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("light.test") @@ -709,7 +709,7 @@ async def test_sending_mqtt_commands_and_optimistic( await common.async_turn_off(hass, "light.test") mqtt_mock.async_publish.assert_called_once_with( - "test_light_rgb/set", '{"state": "OFF"}', 2, False + "test_light_rgb/set", '{"state":"OFF"}', 2, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("light.test") @@ -838,7 +838,7 @@ async def test_sending_mqtt_commands_and_optimistic2( # Turn the light on await common.async_turn_on(hass, "light.test") mqtt_mock.async_publish.assert_called_once_with( - "test_light_rgb/set", '{"state": "ON"}', 2, False + "test_light_rgb/set", '{"state":"ON"}', 2, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("light.test") @@ -848,7 +848,7 @@ async def test_sending_mqtt_commands_and_optimistic2( await common.async_turn_on(hass, "light.test", color_temp=90) mqtt_mock.async_publish.assert_called_once_with( "test_light_rgb/set", - JsonValidator('{"state": "ON", "color_temp": 90}'), + JsonValidator('{"state":"ON","color_temp":90}'), 2, False, ) @@ -859,7 +859,7 @@ async def test_sending_mqtt_commands_and_optimistic2( # Turn the light off await common.async_turn_off(hass, "light.test") mqtt_mock.async_publish.assert_called_once_with( - "test_light_rgb/set", '{"state": "OFF"}', 2, False + "test_light_rgb/set", '{"state":"OFF"}', 2, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("light.test") @@ -2004,7 +2004,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): light.DOMAIN, DEFAULT_CONFIG, light.SERVICE_TURN_ON, - command_payload='{"state": "ON"}', + command_payload='{"state":"ON"}', state_payload='{"state":"ON"}', ) @@ -2038,7 +2038,7 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): light.SERVICE_TURN_ON, "command_topic", None, - '{"state": "ON"}', + '{"state":"ON"}', None, None, None, @@ -2047,7 +2047,7 @@ async def test_max_mireds(hass, mqtt_mock_entry_with_yaml_config): light.SERVICE_TURN_OFF, "command_topic", None, - '{"state": "OFF"}', + '{"state":"OFF"}', None, None, None, diff --git a/tests/components/mqtt/test_siren.py b/tests/components/mqtt/test_siren.py index c3916acb34b..6da9682c1c7 100644 --- a/tests/components/mqtt/test_siren.py +++ b/tests/components/mqtt/test_siren.py @@ -140,7 +140,7 @@ async def test_sending_mqtt_commands_and_optimistic( await async_turn_on(hass, entity_id="siren.test") mqtt_mock.async_publish.assert_called_once_with( - "command-topic", '{"state": "beer on"}', 2, False + "command-topic", '{"state":"beer on"}', 2, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("siren.test") @@ -149,7 +149,7 @@ async def test_sending_mqtt_commands_and_optimistic( await async_turn_off(hass, entity_id="siren.test") mqtt_mock.async_publish.assert_called_once_with( - "command-topic", '{"state": "beer off"}', 2, False + "command-topic", '{"state":"beer off"}', 2, False ) state = hass.states.get("siren.test") assert state.state == STATE_OFF @@ -870,7 +870,7 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): siren.DOMAIN, DEFAULT_CONFIG, siren.SERVICE_TURN_ON, - command_payload='{"state": "ON"}', + command_payload='{"state":"ON"}', ) @@ -881,14 +881,14 @@ async def test_entity_debug_info_message(hass, mqtt_mock_entry_no_yaml_config): siren.SERVICE_TURN_ON, "command_topic", None, - '{"state": "ON"}', + '{"state":"ON"}', None, ), ( siren.SERVICE_TURN_OFF, "command_topic", None, - '{"state": "OFF"}', + '{"state":"OFF"}', None, ), ],