我想将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对象,是不是会更好?


当前回答

我已经编写了一个名为any2any的小型(反)序列化框架,它可以帮助在两种Python类型之间进行复杂的转换。

在您的情况下,我猜您想从字典(通过json.loads获得)转换为复杂的对象response.education;Response.name,具有嵌套结构response.education.id,等等… 这就是这个框架的用途。文档还不是很好,但是通过使用any2any.simple。MappingToObject,你应该可以很容易地做到。如果需要帮助,请询问。

其他回答

改进lovasoa非常好的答案。

如果你正在使用python 3.6+,你可以使用: PIP安装棉花糖-enum和 PIP安装棉花糖数据类

它简单且类型安全。

你可以在string-json中转换你的类,反之亦然:

从对象到字符串Json:

    from marshmallow_dataclass import dataclass
    user = User("Danilo","50","RedBull",15,OrderStatus.CREATED)
    user_json = User.Schema().dumps(user)
    user_json_str = user_json.data

从String Json到Object:

    json_str = '{"name":"Danilo", "orderId":"50", "productName":"RedBull", "quantity":15, "status":"Created"}'
    user, err = User.Schema().loads(json_str)
    print(user,flush=True)

类定义:

class OrderStatus(Enum):
    CREATED = 'Created'
    PENDING = 'Pending'
    CONFIRMED = 'Confirmed'
    FAILED = 'Failed'

@dataclass
class User:
    def __init__(self, name, orderId, productName, quantity, status):
        self.name = name
        self.orderId = orderId
        self.productName = productName
        self.quantity = quantity
        self.status = status

    name: str
    orderId: str
    productName: str
    quantity: int
    status: OrderStatus

在寻找解决方案时,我偶然发现了这个博客:https://blog.mosthege.net/2016/11/12/json-deserialization-of-nested-objects/

它使用与前面回答中相同的技术,但使用了装饰器。 我发现另一件有用的事情是,它在反序列化结束时返回一个类型化对象

class JsonConvert(object):
    class_mappings = {}

    @classmethod
    def class_mapper(cls, d):
        for keys, cls in clsself.mappings.items():
            if keys.issuperset(d.keys()):   # are all required arguments present?
                return cls(**d)
        else:
            # Raise exception instead of silently returning None
            raise ValueError('Unable to find a matching class for object: {!s}'.format(d))

    @classmethod
    def complex_handler(cls, Obj):
        if hasattr(Obj, '__dict__'):
            return Obj.__dict__
        else:
            raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(Obj), repr(Obj)))

    @classmethod
    def register(cls, claz):
        clsself.mappings[frozenset(tuple([attr for attr,val in cls().__dict__.items()]))] = cls
        return cls

    @classmethod
    def to_json(cls, obj):
        return json.dumps(obj.__dict__, default=cls.complex_handler, indent=4)

    @classmethod
    def from_json(cls, json_str):
        return json.loads(json_str, object_hook=cls.class_mapper)

用法:

@JsonConvert.register
class Employee(object):
    def __init__(self, Name:int=None, Age:int=None):
        self.Name = Name
        self.Age = Age
        return

@JsonConvert.register
class Company(object):
    def __init__(self, Name:str="", Employees:[Employee]=None):
        self.Name = Name
        self.Employees = [] if Employees is None else Employees
        return

company = Company("Contonso")
company.Employees.append(Employee("Werner", 38))
company.Employees.append(Employee("Mary"))

as_json = JsonConvert.to_json(company)
from_json = JsonConvert.from_json(as_json)
as_json_from_json = JsonConvert.to_json(from_json)

assert(as_json_from_json == as_json)

print(as_json_from_json)

我已经编写了一个名为any2any的小型(反)序列化框架,它可以帮助在两种Python类型之间进行复杂的转换。

在您的情况下,我猜您想从字典(通过json.loads获得)转换为复杂的对象response.education;Response.name,具有嵌套结构response.education.id,等等… 这就是这个框架的用途。文档还不是很好,但是通过使用any2any.simple。MappingToObject,你应该可以很容易地做到。如果需要帮助,请询问。

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

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

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