将嵌套的 Python OrderedDict 转换为 QJSValue
Convert a nested Python OrderedDict into a QJSValue
我有一些嵌套的 python OrderedDicts,例如
# The Object we need to convert
od = OrderedDict(
[
('header', OrderedDict(
[
('stamp', OrderedDict(
[
('sec', 42),
('nanosec', 99)
]
)
),
('frame_id', 'world')
]
)
),
('name', ['x', 'y', 'z']),
('position', [1.0, 2.0, 3.0]),
('velocity', [0.0, 0.0, 0.0]),
('effort', [0.0, 0.0, 0.0])
]
)
我需要将其转换为 QJSValue。
如果需要,可以为执行此操作的函数提供 QJSValue 原型。这是上述值的原型。这可能会使事情变得更容易,尤其是在转换列表部分时。
# A JS Prototype that has the feilds and types, and just needs its values populating
app = QCoreApplication()
engine = QJSEngine()
joint_state_msg_js = engine.newObject()
header_msg_js = engine.newObject()
stamp_msg_js = engine.newObject()
stamp_msg_js.setProperty('sec',0)
stamp_msg_js.setProperty('nanosec',0)
header_msg_js.setProperty('stamp', stamp_msg_js)
header_msg_js.setProperty('frame_id', '')
joint_state_msg_js.setProperty('header', header_msg_js)
joint_state_msg_js.setProperty('name', engine.newArray(3))
joint_state_msg_js.setProperty('position', engine.newArray(3))
joint_state_msg_js.setProperty('velocity', engine.newArray(3))
joint_state_msg_js.setProperty('effort', engine.newArray(3))
prototype = joint_state_msg_js
print(prototype.toVariant())
OrderedDict 可以有任何深度。
我一直在尝试编写一个从 OrderedDict 创建 QJSValue 或填充原型值的函数,但我不知道该怎么做。它需要与任何 OrderedDict(原始类型或其他 OrderedDicts 的任何 OrderedDict)一起使用。
这个函数怎么写?
这是我的尝试之一:
def to_qjs_value(od: OrderedDict, prototype: QJSValue) -> QJSValue:
for field_name in od:
inner_dict_or_value = od[field_name]
if isinstance(inner_dict_or_value, OrderedDict):
inner_dict = inner_dict_or_value
inner_dict_js = to_qjs_value(inner_dict, prototype) # recursion
prototype.setProperty(field_name, inner_dict_js)
else:
inner_value = inner_dict_or_value
if isinstance(inner_value, list):
jslist = QJSValue()
i=0
for inner_list_value in inner_value:
jslist.setProperty(i, inner_list_value)
i=i+1
prototype.setProperty(field_name, jslist)
else:
prototype.setProperty(field_name, inner_value)
return prototype
但这会使结果变平,并且不会填充列表。
{
'effort': None,
'frame_id': 'world',
'header': {},
'name': None,
'nanosec': 99,
'position': None,
'sec': 42,
'stamp': {},
'velocity': None
}
使用或不使用原型的解决方案都可以。
一种可能的解决方案是使用 json.dumps()
将字典转换为字符串 json,然后使用 JSON.Parse
:
将字符串转换为对象
app = QCoreApplication()
engine = QJSEngine()
od_json = json.dumps(od)
converter = engine.evaluate("JSON.parse")
qjsvalue = converter.call([QJSValue(od_json)])
assert (
qjsvalue.property("header").property("stamp").property("sec").equals(QJSValue(42.0))
)
我有一些嵌套的 python OrderedDicts,例如
# The Object we need to convert
od = OrderedDict(
[
('header', OrderedDict(
[
('stamp', OrderedDict(
[
('sec', 42),
('nanosec', 99)
]
)
),
('frame_id', 'world')
]
)
),
('name', ['x', 'y', 'z']),
('position', [1.0, 2.0, 3.0]),
('velocity', [0.0, 0.0, 0.0]),
('effort', [0.0, 0.0, 0.0])
]
)
我需要将其转换为 QJSValue。
如果需要,可以为执行此操作的函数提供 QJSValue 原型。这是上述值的原型。这可能会使事情变得更容易,尤其是在转换列表部分时。
# A JS Prototype that has the feilds and types, and just needs its values populating
app = QCoreApplication()
engine = QJSEngine()
joint_state_msg_js = engine.newObject()
header_msg_js = engine.newObject()
stamp_msg_js = engine.newObject()
stamp_msg_js.setProperty('sec',0)
stamp_msg_js.setProperty('nanosec',0)
header_msg_js.setProperty('stamp', stamp_msg_js)
header_msg_js.setProperty('frame_id', '')
joint_state_msg_js.setProperty('header', header_msg_js)
joint_state_msg_js.setProperty('name', engine.newArray(3))
joint_state_msg_js.setProperty('position', engine.newArray(3))
joint_state_msg_js.setProperty('velocity', engine.newArray(3))
joint_state_msg_js.setProperty('effort', engine.newArray(3))
prototype = joint_state_msg_js
print(prototype.toVariant())
OrderedDict 可以有任何深度。
我一直在尝试编写一个从 OrderedDict 创建 QJSValue 或填充原型值的函数,但我不知道该怎么做。它需要与任何 OrderedDict(原始类型或其他 OrderedDicts 的任何 OrderedDict)一起使用。
这个函数怎么写?
这是我的尝试之一:
def to_qjs_value(od: OrderedDict, prototype: QJSValue) -> QJSValue:
for field_name in od:
inner_dict_or_value = od[field_name]
if isinstance(inner_dict_or_value, OrderedDict):
inner_dict = inner_dict_or_value
inner_dict_js = to_qjs_value(inner_dict, prototype) # recursion
prototype.setProperty(field_name, inner_dict_js)
else:
inner_value = inner_dict_or_value
if isinstance(inner_value, list):
jslist = QJSValue()
i=0
for inner_list_value in inner_value:
jslist.setProperty(i, inner_list_value)
i=i+1
prototype.setProperty(field_name, jslist)
else:
prototype.setProperty(field_name, inner_value)
return prototype
但这会使结果变平,并且不会填充列表。
{
'effort': None,
'frame_id': 'world',
'header': {},
'name': None,
'nanosec': 99,
'position': None,
'sec': 42,
'stamp': {},
'velocity': None
}
使用或不使用原型的解决方案都可以。
一种可能的解决方案是使用 json.dumps()
将字典转换为字符串 json,然后使用 JSON.Parse
:
app = QCoreApplication()
engine = QJSEngine()
od_json = json.dumps(od)
converter = engine.evaluate("JSON.parse")
qjsvalue = converter.call([QJSValue(od_json)])
assert (
qjsvalue.property("header").property("stamp").property("sec").equals(QJSValue(42.0))
)