Skip to content

Instantly share code, notes, and snippets.

@cppio
Created December 25, 2025 00:19
Show Gist options
  • Select an option

  • Save cppio/9e3fbf6b778454cacc79092a039bc79d to your computer and use it in GitHub Desktop.

Select an option

Save cppio/9e3fbf6b778454cacc79092a039bc79d to your computer and use it in GitHub Desktop.
import plistlib, pprint, sys, uuid
with open(sys.argv[1], "rb") as plist:
plist = plistlib.load(plist)
assert plist["$archiver"] == "NSKeyedArchiver"
objs = plist["$objects"]
def decode(val):
if isinstance(val, dict):
val = {k: decode(v) for k, v in val.items()}
match val.get("$class", {}).get("$classname"):
case "NSString" | "NSMutableString":
return val["NS.string"]
case "NSArray" | "NSMutableArray":
return val["NS.objects"]
case "NSDictionary" | "NSMutableDictionary":
return dict(zip(val["NS.keys"], val["NS.objects"], strict=True))
case "NSUUID":
return uuid.UUID(bytes=val["NS.uuidbytes"])
case "NSNull":
return None
return val
if isinstance(val, list):
return [decode(i) for i in val]
if isinstance(val, plistlib.UID):
return decode(objs[val])
return val
top = decode(plist["$top"])
pprint.pprint(top, width=200, compact=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment