mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-05-14 17:43:32 +00:00
fix(news): custom RSS feed save fails with validation error when no logo (#329)
_set_missing_booleans_to_false was unconditionally creating an empty
dict for every nested-object sub-property when processing array items.
For the news plugin's custom_feeds, this produced logo:{} on every feed
item that had no logo uploaded. jsonschema then validated that empty
object against logo's required:["id","path"] constraint and failed.
Fix: skip recursion into a sub-object when it isn't already present in
the array item. There's no reason to create an optional object like
logo just to look for boolean fields inside it.
Also extend _filter_config_by_schema to recurse into array items when
the items schema has properties. Previously arrays were passed through
unchanged, so any stray field on a feed item (legacy data, migration
artifacts) would survive to validation where additionalProperties:false
would reject it.
Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4277,8 +4277,13 @@ def _set_missing_booleans_to_false(config, schema_props, form_keys, prefix='', c
|
|||||||
elif prop_type == 'object' and 'properties' in prop_schema:
|
elif prop_type == 'object' and 'properties' in prop_schema:
|
||||||
# Recurse into nested objects
|
# Recurse into nested objects
|
||||||
if config_node is not None:
|
if config_node is not None:
|
||||||
# Inside an array item — ensure nested dict exists in item
|
# Inside an array item — only recurse if the sub-object already exists.
|
||||||
if prop_name not in node or not isinstance(node[prop_name], dict):
|
# Never create optional sub-objects that weren't submitted; doing so
|
||||||
|
# produces e.g. logo:{} on feed items with no logo, which then fails
|
||||||
|
# schema validation when the object has required fields (id, path).
|
||||||
|
if prop_name not in node:
|
||||||
|
continue
|
||||||
|
if not isinstance(node[prop_name], dict):
|
||||||
node[prop_name] = {}
|
node[prop_name] = {}
|
||||||
_set_missing_booleans_to_false(
|
_set_missing_booleans_to_false(
|
||||||
config, prop_schema['properties'], form_keys, full_path,
|
config, prop_schema['properties'], form_keys, full_path,
|
||||||
@@ -4418,10 +4423,22 @@ def _filter_config_by_schema(config, schema, prefix=''):
|
|||||||
prop_schema = schema_props[key]
|
prop_schema = schema_props[key]
|
||||||
|
|
||||||
# Handle nested objects recursively
|
# Handle nested objects recursively
|
||||||
|
item_prefix = f"{prefix}.{key}" if prefix else key
|
||||||
if isinstance(value, dict) and prop_schema.get('type') == 'object' and 'properties' in prop_schema:
|
if isinstance(value, dict) and prop_schema.get('type') == 'object' and 'properties' in prop_schema:
|
||||||
filtered[key] = _filter_config_by_schema(value, prop_schema, f"{prefix}.{key}" if prefix else key)
|
filtered[key] = _filter_config_by_schema(value, prop_schema, item_prefix)
|
||||||
|
elif isinstance(value, list) and prop_schema.get('type') == 'array':
|
||||||
|
items_schema = prop_schema.get('items', {})
|
||||||
|
if isinstance(items_schema, dict) and items_schema.get('type') == 'object' and 'properties' in items_schema:
|
||||||
|
# Filter each item in the array so extra fields are stripped before
|
||||||
|
# schema validation (important when items has additionalProperties: false)
|
||||||
|
filtered[key] = [
|
||||||
|
_filter_config_by_schema(item, items_schema, item_prefix) if isinstance(item, dict) else item
|
||||||
|
for item in value
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
# Keep the value as-is for non-object types
|
filtered[key] = value
|
||||||
|
else:
|
||||||
|
# Keep the value as-is for non-object/non-array types
|
||||||
filtered[key] = value
|
filtered[key] = value
|
||||||
|
|
||||||
return filtered
|
return filtered
|
||||||
|
|||||||
Reference in New Issue
Block a user