繁体   English   中英

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

[英]How to inspect mystery deserialized object in Python

我正在尝试将JSON重新加载到对象中。 “加载”方法似乎可以正常工作,但该对象似乎没有我期望的属性。

我该如何检查/检查我拥有的对象(这是基于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)

上面的尝试返回了以下内容:

   Item
     SubItem=__class__

我不认为它很重要,但对于背景:JSON实际上是从谷歌应用程序引擎的REST Web服务创建网址抓取来使用这个工具创建的: http://code.google.com/p/appengine-rest-服务器 正在使用以下定义从数据存储中检索数据:

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'first'':u'Neal'}

我具有Microsoft的背景知识,所以当我听到序列化/反序列化时,我认为是从对象到字符串,再从字符串回到对象。 因此,如果我先序列化为JSON,然后反序列化,我将得到什么,字典,列表或对象? 实际上,我是从REST Web方法获取JSON的,这代表我为我序列化了对象。

理想情况下,我想要一个与上面的Subscriber类匹配的订阅者对象,理想情况下,我不想编写一次性的自定义代码(即特定于“ Subscriber”的代码),因为我想做同样的事情与其他数十个类别。 如果必须编写一些自定义代码,则需要进行一般性的处理,以便它可以与任何类一起使用。

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

如果要执行所有操作,为什么还要将所有内容都作为字典对象。 我不想拥有成熟的课程结构吗? 下一个技巧之一是某种对象关系映射(ORM),这样我们就不必公开确切的数据表,而是公开更多的逻辑层。

我们还希望向可能使用任何语言的付费用户公开RESTful API。 对于他们来说,他们可以使用XML或JSON,并且不会使用此处讨论的序列化例程。

results您的代码段是字典,而不是字符串,因此json.loads会引发异常。 如果是固定的,每个subitem在内环则是一个元组,所以想将它添加到一个字符串作为你正在做会提高其他异常。 我想您已经简化了代码,但是这两个类型错误应该已经表明您简化太多(并且不正确)。 为什么不使用一个(同样简化的) 工作片段,以及您想要json.loads的实际字符串,而不是一个无法重现您的问题的字符串? 采取这种行动将使帮助您变得更加容易。

除了查看实际的字符串并显示一些明显的信息(例如type(subscriber) ,基于清晰可见的代码和不足的信息,很难提供更多帮助:-(。

编辑 :在“ update2”中,OP表示

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

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

JSON是一种完全独立于语言的序列化格式,尽管最初以Javascript为中心,但它绝对不知道您希望看到哪些类(如果有)( 当然没有),并且认为它可能是荒谬的:它怎么可能是与语言无关的,如果硬编码的“类”,一个概念,它的概念本身这么多语言,包括JavaScript,甚至没有 ) - ?!因此它使用(在Python方面)的字符串,数字,列表和字典(任何半体面的现代语言都应具有的四种非常基本的数据类型,至少如果没有嵌入适当的语言,至少在某些库中也是如此!)。 当您json.loads一个字符串时,您总是会得到上述四种数据类型的嵌套组合(所有字符串将是unicode,而所有数字将是浮点数,BTW ;-)。

如果您不知道(并且不想通过某种任意约定或其他方式编码)正在序列化哪个类的实例,但是在反序列化时绝对必须返回类实例(不仅仅是字典等),JSON本身就不能可以帮助您-元信息不能出现在JSON序列化字符串本身中。

如果您对这四种基本类型都没问题,并且只想查看一些比基本类型的默认Python字符串打印更“漂亮”的打印结果,则必须编写自己的递归漂亮打印函数的功能取决于您对“ pretty”的主观定义(我怀疑您是否希望Python自己的pprint标准库模块超出了您当前的结果;-)。

json仅编码字符串,浮点数,整数,javascript对象(python字典)和列表。

您必须创建一个函数,将返回的字典转换为类,然后使用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))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM