如何用Python验证JSON数据格式、类型及指定Value键是否存在
Hey there! Let's tackle your Python JSON validation questions step by step.
验证JSON格式合法性
First up, to check if a string is valid JSON, we can use Python's built-in json module. When the input isn't valid JSON, json.loads() will throw a JSONDecodeError—we can catch this with a try-except block to confirm format validity:
import json def validate_json_format(json_str): try: parsed_data = json.loads(json_str) return True, parsed_data except json.JSONDecodeError as e: return False, f"Invalid JSON: {str(e)}" # Example usage test_json = '{"DeviceInstanceId": 5, "ProductType": "12345"}' is_valid, result = validate_json_format(test_json) if is_valid: print("JSON format is valid!") else: print(result)
验证数据类型和结构
Once you've confirmed the JSON is formatted correctly, you need to check if it matches your expected structure and data types. Here are two common approaches:
Option 1: Manual type checking (good for simple structures)
For straightforward JSON, you can use isinstance() to verify each field's type directly:
def validate_json_structure(data): # First check if the top-level is a list (as per your example) if not isinstance(data, list): return False, "Expected top-level data to be a list" for idx, device in enumerate(data): if not isinstance(device, dict): return False, f"Item {idx+1} in list is not a dictionary" # Check required top-level fields if not isinstance(device.get("DeviceInstanceId"), int): return False, f"DeviceInstanceId in item {idx+1} must be an integer" if not isinstance(device.get("ProductType"), str): return False, f"ProductType in item {idx+1} must be a string" # Check nested structures product = device.get("Product", {}) if not isinstance(product.get("Family"), str): return False, f"Product.Family in item {idx+1} must be a string" return True, "All structure and type checks passed" # Example usage parsed_data = json.loads(test_json) is_valid, msg = validate_json_structure(parsed_data) print(msg)
Option 2: Use the jsonschema library (recommended for complex structures)
Manual checking gets messy for nested or complex JSON. The jsonschema library lets you define a schema and validate against it automatically. First install it with pip install jsonschema, then:
from jsonschema import validate, ValidationError # Define your schema to match expected structure/types device_schema = { "type": "array", "items": { "type": "object", "properties": { "DeviceInstanceId": {"type": "integer"}, "IsResetNeeded": {"type": ["null", "boolean"]}, "ProductType": {"type": "string"}, "Product": { "type": "object", "properties": {"Family": {"type": "string"}}, "required": ["Family"] }, "Device": { "type": "object", "properties": { "ManualAdded": {"type": "object", "properties": {"Value": {"type": "boolean"}}}, "Location": {"type": "object", "properties": {"Value": {"type": "string"}}} }, "required": ["ManualAdded", "Location"] } }, "required": ["DeviceInstanceId", "ProductType", "Product", "Device"] } } def validate_with_schema(data): try: validate(instance=data, schema=device_schema) return True, "Schema validation passed" except ValidationError as e: return False, f"Schema validation failed: {str(e)}" # Example usage is_valid, msg = validate_with_schema(parsed_data) print(msg)
First, let's load your JSON data into a Python object, then check for the "Value" keys. Your JSON has two "Value" keys (under Device.ManualAdded and Device.Location), so we can target those specific paths or search recursively.
Check for "Value" keys in known paths
Since your structure is fixed, we can directly check the expected locations:
import json # Your provided JSON data input_json = '''[ { "DeviceInstanceId": 5, "IsResetNeeded": null, "ProductType": "12345", "Product": { "Family": "12345" }, "Device": { "DeviceFirmwareUpdate": { "DeviceUpdateStatus": null, "DeviceUpdateInProgress": null, "DeviceUpdateProgress": null, "LastDeviceUpdateId": null }, "ManualAdded": { "Value": false }, "Location":{ "Value":"bangalore" } } } ]''' parsed_data = json.loads(input_json) def check_value_keys(data): missing_paths = [] for idx, device in enumerate(data): # Check ManualAdded.Value manual_added = device.get("Device", {}).get("ManualAdded", {}) if "Value" not in manual_added: missing_paths.append(f"Item {idx+1}: Device.ManualAdded.Value") # Check Location.Value location = device.get("Device", {}).get("Location", {}) if "Value" not in location: missing_paths.append(f"Item {idx+1}: Device.Location.Value") if missing_paths: print("Missing 'Value' keys at these paths:") for path in missing_paths: print(f"- {path}") return False else: print("All expected 'Value' keys are present!") return True # Run the check all_values_found = check_value_keys(parsed_data)
Recursively find all "Value" keys (for unknown structures)
If you need to find every instance of "Value" regardless of location, use a recursive function:
def find_all_value_keys(obj, current_path=""): found_paths = [] if isinstance(obj, dict): for key, value in obj.items(): new_path = f"{current_path}.{key}" if current_path else key if key == "Value": found_paths.append(new_path) else: found_paths.extend(find_all_value_keys(value, new_path)) elif isinstance(obj, list): for idx, item in enumerate(obj): new_path = f"{current_path}[{idx}]" if current_path else f"[{idx}]" found_paths.extend(find_all_value_keys(item, new_path)) return found_paths # Example usage found_value_paths = find_all_value_keys(parsed_data) print("Found 'Value' keys at:") for path in found_value_paths: print(f"- {path}")
若"Value"键不存在的后续处理思路
How you handle missing "Value" keys depends on your business needs:
- Log a warning: Record the missing path and device details in a log for later debugging.
- Set a default value: If the field isn't mandatory, assign a sensible default (e.g.,
FalseforManualAdded.Value, empty string forLocation.Value). - Throw an exception: If "Value" is required for your workflow, raise a
ValueErroror custom exception to halt processing and enforce data integrity. - Skip invalid entries: If partial data is acceptable, skip the device with missing keys and continue processing valid entries.
内容的提问来源于stack exchange,提问作者nrs

