我想将JSON数据转换为Python对象。

我从Facebook API收到JSON数据对象,我想将其存储在数据库中。

我的当前视图在Django (Python)(请求。POST包含JSON):

response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()

这很好,但是如何处理复杂的JSON数据对象呢? 如果我能以某种方式将这个JSON对象转换为易于使用的Python对象,是不是会更好?


当前回答

如果你使用的是Python 3.5+,你可以使用json来序列化和反序列化到普通的旧Python对象:

import jsons

response = request.POST

# You'll need your class attributes to match your dict keys, so in your case do:
response['id'] = response.pop('user_id')

# Then you can load that dict into your class:
user = jsons.load(response, FbApiUser)

user.save()

你也可以让FbApiUser从jsons继承。JsonSerializable更优雅:

user = FbApiUser.from_json(response)

如果你的类由Python默认类型组成,比如字符串、整数、列表、日期时间等,这些例子就可以工作。不过,jsons lib需要自定义类型的类型提示。

其他回答

使用json模块(Python 2.6新增)或几乎总是安装的simplejson模块。

对于复杂的对象,可以使用JSON Pickle

Python库,用于将任意对象图序列化为JSON。 它几乎可以接受任何Python对象并将对象转换为JSON。 此外,它还可以将对象重新构造回Python。

JSON到python对象

下面的代码递归地使用对象键创建动态属性。

JSON对象- fb_data.json:

{
    "name": "John Smith",
    "hometown": {
        "name": "New York",
        "id": 123
    },
    "list": [
        "a",
        "b",
        "c",
        1,
        {
            "key": 1
        }
    ],
    "object": {
        "key": {
            "key": 1
        }
    }
}

在转换中我们有三种情况:

列表 Dicts(新对象) Bool, int, float和STR

import json


class AppConfiguration(object):
    def __init__(self, data=None):
        if data is None:
            with open("fb_data.json") as fh:
                data = json.loads(fh.read())
        else:
            data = dict(data)

        for key, val in data.items():
            setattr(self, key, self.compute_attr_value(val))

    def compute_attr_value(self, value):
        if isinstance(value, list):
            return [self.compute_attr_value(x) for x in value]
        elif isinstance(value, dict):
            return AppConfiguration(value)
        else:
            return value


if __name__ == "__main__":
    instance = AppConfiguration()

    print(instance.name)
    print(instance.hometown.name)
    print(instance.hometown.id)
    print(instance.list[4].key)
    print(instance.object.key.key)

键值对是属性-对象。

输出:

John Smith
New York
123
1
1

将JSON作为代码粘贴

支持TypeScript、Python、Go、Ruby、c#、Java、Swift、Rust、Kotlin、c++、Flow、Objective-C、JavaScript、Elm、JSON Schema。

从JSON、JSON Schema和TypeScript中交互式地生成类型和(反)序列化代码 将JSON/JSON Schema/TypeScript作为代码粘贴

quicktype从示例JSON数据中推断类型,然后输出强类型模型和序列化器,以便用所需的编程语言处理这些数据。

输出:

# Generated by https://quicktype.io
#
# To change quicktype's target language, run command:
#
#   "Set quicktype target language"

from typing import List, Union


class Hometown:
    name: str
    id: int

    def __init__(self, name: str, id: int) -> None:
        self.name = name
        self.id = id


class Key:
    key: int

    def __init__(self, key: int) -> None:
        self.key = key


class Object:
    key: Key

    def __init__(self, key: Key) -> None:
        self.key = key


class FbData:
    name: str
    hometown: Hometown
    list: List[Union[Key, int, str]]
    object: Object

    def __init__(self, name: str, hometown: Hometown, list: List[Union[Key, int, str]], object: Object) -> None:
        self.name = name
        self.hometown = hometown
        self.list = list
        self.object = object

这个扩展可以在Visual Studio代码市场中免费获得。

class SimpleClass:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            if type(v) is dict:
                setattr(self, k, SimpleClass(**v))
            else:
                setattr(self, k, v)


json_dict = {'name': 'jane doe', 'username': 'jane', 'test': {'foo': 1}}

class_instance = SimpleClass(**json_dict)

print(class_instance.name, class_instance.test.foo)
print(vars(class_instance))

如果你使用的是Python 3.6或更新版本,你可以看看squema——一个用于静态类型数据结构的轻量级模块。它使您的代码易于阅读,同时提供简单的数据验证,转换和序列化,而无需额外的工作。你可以把它看作是命名元组和数据类的一种更复杂、更有见解的选择。下面是你如何使用它:

from uuid import UUID
from squema import Squema


class FbApiUser(Squema):
    id: UUID
    age: int
    name: str

    def save(self):
        pass


user = FbApiUser(**json.loads(response))
user.save()