当我尝试使用
plutil -convert json -
将 Plist 转换为 JSON 时,由于输入中的对象无效,它给我一个错误。例如:
$ ioreg -rw0 -c AppleSmartBattery -a | plutil -convert json -
<stdin>: invalid object in plist for destination format
当输入包含 JSON 格式的无效对象时,如何将 Plist 转换为 JSON?
当 plist 包含与 6 种 JSON 类型(字符串、数字、布尔值、数组、对象、null)不兼容的数据时,就会发生这种情况。最常见(可能是唯一?)的示例是二进制数据。
Python 有一个用于解析 plist 数据的内置库,当对象与 JSON 不兼容时,它还允许我们方便地指定自定义行为以序列化为 JSON。
这让我们可以创建一个相对简单的 python 单行代码(在 shell 中使用)或一个可以在 python 代码中使用的函数,其中我们指定如何处理无法序列化为 JSON 的二进制数据。
我的首选方法是对二进制数据进行 Base64 编码,并在其前面加上
base64:
,这样当我将来需要时,数据仍然可用。这是我的 shell 单行代码,我可以将 plist 输出通过管道传输到其中:
python -c 'import plistlib,sys,json,base64; print(json.dumps(plistlib.loads(sys.stdin.read().encode("utf-8")), default=lambda o:"base64:"+base64.b64encode(o).decode("ascii")))'
这是多行编写的代码,因此您可以看到它在做什么:
import plistlib
import sys
import json
import base64
stdin_bytes = sys.stdin.read()
stdin_str = stdin_bytes.encode("utf-8")
plist_data = plistlib.loads(stdin_str)
def json_default_fn(o):
return "base64:" + base64.b64encode(o).decode('ascii')
json_data = json.dumps(plist_data, default=json_default_fn)
print(json_data)
我的建议是将单行代码包装在 bash/zsh/sh 函数中,并将其放入您的
.bashrc
/.zshrc
/.profile
/等中。使其易于使用:
plist_to_json() {
python -c 'import plistlib,sys,json,base64; print(json.dumps(plistlib.loads(sys.stdin.read().encode("utf-8")), default=lambda o:"base64:"+base64.b64encode(o).decode("ascii")))'
}
使用示例(打印 MacBook 电池信息):
$ ioreg -rw0 -c AppleSmartBattery -a | plist_to_json
请注意,如果您关心正在编码的二进制数据,则可以在 json 转储中使用不同的默认函数,例如
lambda o: "<Not Serializable>"
将二进制字段设置为固定字符串。
正如Christopher Shroba所说:
当 plist 包含与 6 种 JSON 类型(字符串、数字、布尔值、数组、对象、null)不兼容的数据时,就会发生这种情况。最常见(可能是唯一?)的示例是二进制数据。
Plist 拥有 8 种类型(bool、integer、float、string、dictionary、array、date、data),您可以尝试 sed 与 JSON 不兼容的类型。
它对我来说效果很好:
ioreg -r -k BatteryPercent -a | sed 's/data/string/g' | plutil -convert json -o okk.json
希望可以帮到你~