我正在尝试使用jsons将json字符串反序列化为对象,但是嵌套对象有问题,但是无法计算语法。
作为示例,以下代码尝试将数据结构定义为一系列数据类,但未能反序列化嵌套对象C和D?语法显然是错误的,但对我来说尚不清楚应如何构造
http://torrent.ubuntu.com:6969/announce
谁能指出从json反序列化对象的正确方法?
答案 0 :(得分:1)
您的尝试有两个相对简单的问题:
C
装饰@dataclass
。Test.C
和Test.D
不是用类型定义的,而是用这些类型的 instances 定义的。 (此外,您希望两个字段都是给定类型的列表,而不是每个字段的单个实例。)给出代码
import jsons
from dataclasses import dataclass
from typing import List
@dataclass
class D:
E: str
@dataclass # Problem 1 fixed
class C:
id: int
name: str
@dataclass
class Test:
A: str
B: int
C: List[C] # Problem 2 fixed; List[C] not C() or even C
D: List[D] # Problem 2 fixed; List[D], not D() or even D
然后
>>> obj = {"A":"a", "B":1, "C": [{"id": 1,"name": "one"}, {"id": 2, "name": "two"}], "D":[{"E": "e"}]}
>>> jsons.load(obj, Test)
test(A='a', B=1, C=[C(id=1, name='one'), C(id=2, name='two')], D=[D(E='e')])
答案 1 :(得分:0)
您可以执行以下操作:
from collections import namedtuple
# First parameter is the class/tuple name, second parameter
# is a space delimited string of varaibles.
# Note that the variable names should match the keys from
# your dictionary of arguments unless only one argument is given.
A = namedtuple("A", "a_val") # Here the argument `a_val` can be called something else
B = namedtuple("B", "num")
C = namedtuple("C", "id name")
D = namedtuple("D", "E") # This must be `E` since E is the key in the dictionary.
# If you dont want immutable objects to can use full classes
# instead of namedtuples
# A dictionary which matches the name of an object seen in a payload
# to the object we want to create for that name.
object_options = {
"A": A,
"B": B,
"C": C,
"D": D
}
my_objects = [] # This is the list of object we get from the payload
jsonString = {"A":"a","B":1,"C":[{"id":1,"name":"one"},{"id":2,"name":"two"}],"D":[{"E":"e"}]}
for key, val in jsonString.items():
if key in object_options: # If this is a valid object
if isinstance(val, list): # If it is a list of this object
for v in val: # Then we need to add each object in the list
my_objects.append(object_options[key](**v))
elif isinstance(val, dict): # If the object requires a dict then pass the whole dict as arugments
my_objects.append(object_options[key](**val))
else: # Else just add this object with a singular argument.
my_objects.append(object_options[key](val))
print(my_objects)
输出:
[A(a_val='a'), B(num=1), C(id=1, name='one'), C(id=2, name='two'), D(E='e')]
答案 2 :(得分:0)
我终于设法通过删除dataClass
定义并扩展了旧的类定义来使它生效。...代码如下...
import jsons
class D:
def __init__(self, E = ""):
self.E = E
class C:
def __init__(self, id = 0, name=""):
self.id = id
self.name = name
class test:
def __init__(self, A = "", B = 0, C = C(), D = D()):
self.A = A
self.B = B
self.C = C
self.D = D
jsonString = {"A":"a","B":1,"C":[{"id":1,"name":"one"},{"id":2,"name":"two"}],"D":[{"E":"e"}]}
instance = jsons.load(jsonString, test)
它现在可以工作,但不如dataClass
干净。如果有人能指出如何使用dataClass
定义来构造原始帖子,将不胜感激。
答案 3 :(得分:0)
from dataclasses import dataclass
from typing import List
from validated_dc import ValidatedDC
@dataclass
class D(ValidatedDC):
E: str
@dataclass
class C(ValidatedDC):
id: int
name: str
@dataclass
class Test(ValidatedDC):
A: str
B: int
C: List[C]
D: List[D]
jsonString = {
"A": "a",
"B": 1,
"C": [{"id": 1, "name": "one"}, {"id": 2, "name": "two"}],
"D": [{"E": "e"}]
}
instance = Test(**jsonString)
assert instance.C == [C(id=1, name='one'), C(id=2, name='two')]
assert instance.C[0].id == 1
assert instance.C[1].name == 'two'
assert instance.D == [D(E='e')]
assert instance.D[0].E == 'e'
ValidatedDC:https://github.com/EvgeniyBurdin/validated_dc