The open source OpenXR runtime
at main 4.9 kB view raw
1#!/usr/bin/env python3 2# Copyright 2025, NVIDIA CORPORATION. 3# SPDX-License-Identifier: BSL-1.0 4""" 5Helper script to merge multiple JSON files into one. 6 7This script merges the root JSON objects from multiple input files 8while preserving field ordering. Files are processed in sorted order 9to ensure consistent results. Fields are merged in the order they 10appear across the input files. 11""" 12 13import argparse 14import json 15import sys 16from pathlib import Path 17 18 19def merge_json_files(json_files, output_file, allow_overwrite=False, 20 ignore_schema=False): 21 """ 22 Merge multiple JSON files into a single output file. 23 24 Args: 25 json_files: List of paths to JSON files to merge 26 output_file: Path to the output file 27 allow_overwrite: If True, allow later files to overwrite keys 28 from earlier files 29 ignore_schema: If True, ignore the "$schema" field in input files 30 """ 31 merged = {} 32 33 # Sort files to ensure consistent ordering 34 sorted_files = sorted(json_files) 35 36 for json_file in sorted_files: 37 try: 38 with open(json_file, 'r', encoding='utf-8') as f: 39 data = json.load(f) 40 41 if not isinstance(data, dict): 42 print(f"Error: {json_file} does not contain a JSON " 43 f"object at root level", 44 file=sys.stderr) 45 sys.exit(1) 46 47 # Merge while preserving order - check for duplicates 48 for key, value in data.items(): 49 if key == "$schema" and ignore_schema: 50 continue 51 if key in merged: 52 if allow_overwrite: 53 print(f"Warning: Key '{key}' from {json_file} " 54 f"overwrites previous definition", 55 file=sys.stderr) 56 else: 57 print(f"Error: Duplicate key '{key}' found in " 58 f"{json_file}. Use --allow-overwrite to " 59 f"permit overwriting.", 60 file=sys.stderr) 61 sys.exit(1) 62 merged[key] = value 63 64 except FileNotFoundError: 65 print(f"Error: File not found: {json_file}", file=sys.stderr) 66 sys.exit(1) 67 except json.JSONDecodeError as e: 68 print(f"Error: Failed to parse JSON from {json_file}: {e}", 69 file=sys.stderr) 70 sys.exit(1) 71 except Exception as e: 72 print(f"Error: Failed to read {json_file}: {e}", 73 file=sys.stderr) 74 sys.exit(1) 75 76 77 # Write merged JSON to output file 78 try: 79 with open(output_file, 'w', encoding='utf-8') as f: 80 json.dump(merged, f, indent='\t', ensure_ascii=False) 81 f.write('\n') # Add trailing newline 82 83 # Printing, left in if we want it in the future. 84 if False: 85 print(f"Successfully merged {len(json_files)} file(s) into " 86 f"{output_file}") 87 except Exception as e: 88 print(f"Error: Failed to write to {output_file}: {e}", 89 file=sys.stderr) 90 sys.exit(1) 91 92 93def main(): 94 parser = argparse.ArgumentParser( 95 description='Merge multiple JSON files into one, preserving ' 96 'field ordering.', 97 formatter_class=argparse.RawDescriptionHelpFormatter, 98 epilog=""" 99Examples: 100 %(prog)s -o merged.json file1.json file2.json file3.json 101 %(prog)s -o output.json base.json overrides.json 102 %(prog)s -o output.json --allow-overwrite base.json overrides.json 103 %(prog)s -o output.json --ignore-schema schema.json data.json 104 """ 105 ) 106 107 parser.add_argument('-o', '--output', 108 required=True, 109 metavar='OUTPUT', 110 help='Output file path for the merged JSON') 111 112 parser.add_argument('--allow-overwrite', 113 action='store_true', 114 help='Allow later files to overwrite duplicate ' 115 'keys from earlier files') 116 117 parser.add_argument('--ignore-schema', 118 action='store_true', 119 help='Ignore the "$schema" field in input files') 120 121 parser.add_argument('json_files', 122 nargs='+', 123 metavar='JSON_FILE', 124 help='JSON files (will be sorted alphabetically)') 125 126 args = parser.parse_args() 127 128 # Validate that we have at least one input file 129 if not args.json_files: 130 print("Error: At least one JSON file must be provided", 131 file=sys.stderr) 132 sys.exit(1) 133 134 merge_json_files(args.json_files, args.output, args.allow_overwrite, 135 args.ignore_schema) 136 137 138if __name__ == '__main__': 139 main()