如何在Python中检查神秘的反序列化对象

2024-09-27 21:25:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将JSON加载回一个对象中。“loads”方法似乎工作正常,但对象似乎没有我期望的属性。在

如何检查/检查我拥有的对象(这是基于web的代码)。在

  results = {"Subscriber": {"firstname": "Neal", "lastname": "Walters"}}
  subscriber = json.loads(results)


  for item in inspect.getmembers(subscriber): 
     self.response.out.write("<BR>Item")
     for subitem in item: 
         self.response.out.write("<BR>&nbsp;SubItem=" + subitem)

上面的尝试返回了:

^{pr2}$

我不认为这很重要,但就上下文而言: JSON实际上来自googleappengine中的urlphetch 使用此实用程序创建的rest web服务: http://code.google.com/p/appengine-rest-server。 正在从具有以下定义的数据存储中检索数据:

class Subscriber(db.Model):
    firstname    = db.StringProperty()
    lastname     = db.StringProperty()

谢谢, 尼尔

更新1:基本上我正在尝试将JSON反序列化回一个对象。 理论上它是从一个对象序列化的,现在我想把它放回一个对象中。 也许更好的问题是怎么做?在

更新2:我试图将一个复杂的程序抽象成几行代码,所以我在“伪编码”中犯了一些错误,以便在这里发布。在

这里有一个更好的代码示例,现在拿出我可以在PC上运行的网站

results = '{"Subscriber": {"firstname": "Neal", "lastname": "Walters"}}'
subscriber = json.loads(results)
for key, value in subscriber.items():
    print " %s: %s" %(key, value)

在上面的运行中,它显示的内容看起来并不比JSON字符串本身更结构化。显示如下: 订户:{u'lastname':u'Walters',u'firstname':u'Neal'}

我有更多的微软背景,所以当我听到序列化/反序列化时,我认为从一个对象到一个字符串,再从一个字符串回到一个对象。所以,如果我序列化为JSON,然后反序列化,我会得到什么,一个字典,一个列表,还是一个对象?实际上,我是从restwebmethod获取JSON,它代表我序列化对象。在

理想情况下,我想要一个与上面的subscriber类相匹配的subscriber对象,理想情况下,我不想编写一次性的自定义代码(即特定于“subscriber”的代码),因为我希望对其他几十个类执行相同的操作。如果我必须编写一些自定义代码,我将需要一般性地这样做,以便它可以与任何类一起工作。在

更新3:这是为了解释为什么我认为这是一个必要的工具。我正在写一个巨大的应用,可能是在谷歌应用引擎(GAE)上。我们倾向于使用REST架构有几个原因,但一个原因是我们的webgui应该通过restweb层访问数据存储。(我更习惯使用SOAP,所以切换到REST本身就是一个小挑战)。因此,获取和更新数据的经典方法之一就是通过业务或数据层。通过使用上面提到的REST实用程序,我可以选择XML或JSON。我希望在我们开发这个巨大的应用程序之前,先做一个小型的工作原型。那么,假设我们有一个成功的应用程序,并且GAE将其价格加倍。然后我们就可以重写数据层,并使用Python/Django用户层(web代码),在Amazon或其他地方运行它。在

如果我要这么做,为什么我要让所有的东西都是字典对象呢。我难道不想要成熟的阶级结构的力量吗?下一个技巧是某种对象关系映射(object-relational mapping,ORM),这样我们就不必公开确切的数据表,而更像是一个逻辑层。在

我们还希望向可能使用任何语言的付费用户公开restfulapi。对于它们来说,它们可以使用XML或JSON,而不会使用这里讨论的序列化例程。在


Tags: 数据对象代码webjsonfor序列化firstname
3条回答

json只对字符串、浮点、整数、javascript对象(python dict)和列表进行编码。在

您必须创建一个函数来将返回的字典转换为一个类,然后使用object_hook关键字参数和json字符串将其传递给json.loads。下面是一些代码来充实它:

import json

class Subscriber(object):
    firstname = None
    lastname = None


class Post(object):
    author = None
    title = None


def decode_from_dict(cls,vals):
    obj = cls()
    for key, val in vals.items():
        setattr(obj, key, val)
    return obj


SERIALIZABLE_CLASSES = {'Subscriber': Subscriber,
                        'Post': Post}

def decode_object(d):
    for field in d:
        if field in SERIALIZABLE_CLASSES:
            cls = SERIALIZABLE_CLASSES[field]
            return decode_from_dict(cls, d[field])
    return d


results = '''[{"Subscriber": {"firstname": "Neal", "lastname": "Walters"}},
              {"Post": {"author": {"Subscriber": {"firstname": "Neal",
                                                  "lastname": "Walters"}}},
                        "title": "Decoding JSON Objects"}]'''
result = json.loads(results, object_hook=decode_object)
print result
print result[1].author

这将处理任何可以实例化而不需要构造函数参数的类,setattr将为其工作的类。在

另外,这使用json。我对simplejson没有经验,所以YMMV,但我听说他们是一样的。在

请注意,尽管两个订阅服务器对象的值相同,但结果对象却不同。这可以通过记忆decode_from_dict类来解决。在

我猜loads正在返回一个字典。若要迭代其内容,请使用类似于:

for key, value in subscriber.items():
    self.response.out.write("%s: %s" %(key, value))

片段中的results是dict,而不是字符串,因此json.loads将引发异常。如果这是固定的,那么内部循环中的每个subitem都是一个元组,因此尝试将其添加到字符串中会引发另一个异常。我想您已经简化了代码,但是这两个类型的错误应该已经表明您简化了代码太多(而且不正确)。为什么不使用一个(同样简化的)工作代码段,以及您想要json.loads的实际字符串,而不是一个不可能重现问题的字符串呢?这样做会使帮助你更容易。在

除了观察实际的字符串,并显示一些明显的信息,如type(subscriber),很难提供更多的帮助,基于这些明显损坏的代码和在队形:-(. 在

编辑:在“更新2”中,操作员说

It displays this: Subscriber: {u'lastname': u'Walters', u'firstname': u'Neal'}

…还有什么能显示的呢,祈祷?!您将键打印为字符串,然后将值作为字符串key一个字符串,该值是另一个dict,所以它当然是“stringized”(JSON中的所有字符串都是Unicode的,就像在C或Java中一样,而且您说您来自MSFT背景,所以这一点为什么会让您感到惊讶?!)。str(somedict),与repr(somedict)相同,显示了键和值的repr(四周用大括号括起来,冒号和逗号作为适当的分隔符)。在

JSON,一种完全独立于语言的序列化格式,虽然最初是以Javascript为中心的,但它完全不知道您希望看到的(ofcourse的)哪些类(如果有的话),并且认为它可能是不合理的:如果将“类”的概念,很多语言,包括Javascript,都没有这个概念因此,它使用(用Python术语)字符串、数字、列表和dict(四种非常基本的数据类型,任何半正统的现代语言都可以拥有,至少在某些库中,如果没有嵌入到语言本身中的话)。当您json.loads一个字符串时,您将始终得到上述四种数据类型的某种嵌套组合(所有字符串都是unicode,所有数字都是floats,BTW;-)。在

如果您不知道(也不想通过某种任意约定或其他方式编码)正在序列化哪些类的实例,但绝对地,必须在反序列化时返回类实例(而不仅仅是dicts等),那么JSON本身无法帮助您发现元信息不可能存在于JSON序列化字符串本身中。在

如果您对这四种基本类型没问题,只想看到一些打印结果,而您认为这些打印结果比所讨论的基本类型的默认Python字符串打印“更漂亮”,您必须根据您对“pretty”的主观定义编写自己的递归pretty打印函数(我怀疑您是否喜欢Python自己的pprint标准库模块,而不是喜欢当前的结果;-)。在

相关问题 更多 >

    热门问题