0

我正在尝试使用jsons将 json 字符串反序列化为对象,但嵌套对象存在问题,但无法解决语法问题。

例如,以下代码尝试将数据结构定义为一系列数据类,但未能反序列化嵌套对象 C 和 D ?语法显然是错误的,但我不清楚它应该如何构建

import jsons
from dataclasses import dataclass

@dataclass
class D:
    E: str
class C:
    id: int
    name:str
@dataclass
class test:
    A: str
    B: int
    C: C()
    D: D()

jsonString = {"A":"a","B":1,"C":[{"id":1,"name":"one"},{"id":2,"name":"two"}],"D":[{"E":"e"}]}
instance = jsons.load(jsonString, test)

谁能指出从 json 反序列化对象的正确方法?

4

4 回答 4

2

您的尝试有两个相对简单的问题:

  1. 你忘了C@dataclass.
  2. Test.C并且Test.D不是用类型定义的,而是用类型的实例定义的。(此外,您希望两个字段都是给定类型的列表,而不是每个字段的单个实例。)

给定代码

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')])
于 2019-04-22T19:25:26.133 回答
1
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

于 2020-05-28T09:25:47.837 回答
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定义构建原始帖子,将不胜感激。

于 2019-04-22T18:50:46.317 回答
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')]
于 2019-04-22T18:05:31.250 回答