为什么这个 JSON 文件不能用 __dict__ = json.load(f) 解析到我的对象中?

Why won't this JSON file parse into my object with __dict__ = json.load(f)?

我有一个 json 文件,其中包含以下文本:

{"_firstName": "John", "_lastName": "Baker", "_middleName": null, "_mobile": "7609984356", "_education": "Harvard", "_skills": null, "_email": "john@baker.com"}

我正在尝试将其加载到这个 Python 对象中:

class Profile():
    def __init__(self):
        self._firstName = None
        self._lastName = None
        self._middleName = None
        self._mobile = None
        self._education = None
        self._skills = []
        self._email = None

我正在使用:

def profileImport(self):
    with open("../tests/profile.json", "r") as f:
        self._prof.__dict__ = json.load(f)

self._prof.__dict__ = json.load(f) 未正确加载 JSON 数据。我没有从该行收到错误,但该对象具有所有 None 类型,表明该行未成功加载 json 数据。但是,如果我使用 json.loads(),我确实得到了字符串形式的有效 json 数据,这表明正在访问正确的文件。为什么 self._prof.__dict__ = json.load(f) 无法将数据解析到我的对象中?我正在使用 Python 3.6.9.

为此,我会使用 dataclass 和 class 方法。

from dataclasses import dataclass, field
from typing import List
import json


@dataclass
class Profile:
    _firstName: str
    _lastName: str
    _mobile: str
    _education: str
    _email: str
    _skills: List[str] = field(default_factory=list)
    _middleName: str = ""

    def __post_init__(self):
        if self._skills is None:
            self._skills = []
        if self._middleName is None:
            self._middleName = ""

    @classmethod
    def from_json(cls, f):
        return cls(**json.load(f))


with open("tmp.json") as f:
    profile = Profile.from_json(f)

想法是 class 方法处理调用 json.load 并将生成的 key/value 对传递给 __init__ 的工作,它是自动生成的以设置所需的字段。 __post_init__ 负责转换 None 由 JSON 对象提供的值转换为 "real" 默认值。

您可能不需要 class 中的 __init__ 来创建 class 具有 json 文件中的值的实例。

只需 @classmethod 即可将 json 文件加载到 class 实例中,如下所示:

import json

class Profile:
    @classmethod
    def from_json(cls, json_file):
        for key, value in json.load(open(json_file)).items():
            setattr(cls, key, value)
        return cls

现在您可以像这样创建一个实例:

profile = Profile.from_json('/path/to/file.json')
profile._email  # --> "john@baker.com"