Repository: getmoto/moto (python)

Issue:
Feature idea: assert Eventbridge/events Detail field is a dict
This one trips me up the entire time

Eventbridge/events Detail field is required by AWS to be a JSON object (Python dict)

I accidentally send it JSON lists all the time

Production Eventbridge just silently ignores them, leading to mucho head scratching and frustration

Moto events seems to silently allow list sending also

It would be great if moto events could raise a warning/exception on encountering a Detail in list form!

Just a thought

Pull request description:
Events: put_events() now throws a warning when Detail field is not a dict
Fixes #6874 

Patch:
diff --git a/moto/events/models.py b/moto/events/models.py
index 5ec5a318c..d8d0cc229 100644
--- a/moto/events/models.py
+++ b/moto/events/models.py
@@ -1327,7 +1327,11 @@ class EventsBackend(BaseBackend):
                 )
             else:
                 try:
-                    json.loads(event["Detail"])
+                    detail = json.loads(event["Detail"])
+                    if not isinstance(detail, dict):
+                        warnings.warn(
+                            f"EventDetail should be of type dict - types such as {type(detail)} are ignored by AWS"
+                        )
                 except ValueError:  # json.JSONDecodeError exists since Python 3.5
                     entries.append(
                         {


Test patch:
diff --git a/tests/test_events/test_events.py b/tests/test_events/test_events.py
index baf35da3a..0c8f6c667 100644
--- a/tests/test_events/test_events.py
+++ b/tests/test_events/test_events.py
@@ -1,13 +1,14 @@
 import json
 import random
 import unittest
+import warnings
 from datetime import datetime, timezone
 
 import boto3
 import pytest
 from botocore.exceptions import ClientError
 
-from moto import mock_logs
+from moto import mock_logs, settings
 from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
 from moto.core.utils import iso_8601_datetime_without_milliseconds
 from moto.events import mock_events
@@ -682,6 +683,12 @@ def test_put_events():
     assert response["FailedEntryCount"] == 0
     assert len(response["Entries"]) == 1
 
+    if settings.TEST_DECORATOR_MODE:
+        event["Detail"] = json.dumps([{"Key": "k", "Value": "v"}])
+        with warnings.catch_warnings(record=True) as w:
+            client.put_events(Entries=[event])
+        assert "EventDetail should be of type dict" in str(w[0].message)
+
 
 @mock_events
 def test_put_events_error_too_many_entries():