Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python JSON编码/解码GTK枚举_Python_Json_Gtk_Pygtk - Fatal编程技术网

Python JSON编码/解码GTK枚举

Python JSON编码/解码GTK枚举,python,json,gtk,pygtk,Python,Json,Gtk,Pygtk,我必须将自定义GTK元素的各种属性保存到一个文件中以备将来使用,并决定使用JSON,因为DICT的格式和嵌套非常简单 许多属性都是GTK枚举,比如GTK.PAGE\u ORIENTATION\u patriot,GTK.ANCHOR\u CENTER和pango.ALIGN\u LEFT。它们有一个唯一的名称,可以使用obj.value\u name检索该名称以获取有效的JSON类型 目前,我的每个元素都有两种方法:to_str()获取值\u name,以及from_str()将str再次映射到

我必须将自定义GTK元素的各种属性保存到一个文件中以备将来使用,并决定使用JSON,因为DICT的格式和嵌套非常简单

许多属性都是GTK枚举,比如
GTK.PAGE\u ORIENTATION\u patriot
GTK.ANCHOR\u CENTER
pango.ALIGN\u LEFT
。它们有一个唯一的名称,可以使用
obj.value\u name
检索该名称以获取有效的JSON类型

目前,我的每个元素都有两种方法:
to_str()
获取值\u name,以及
from_str()
将str再次映射到枚举。我想自动化这一点,所以我不会忘记调用这些,并清理代码一点。JSONEncoder和JSONDECODER正是这样做的,或者我认为

这是Python文档中给出的示例,它可以按预期工作

import json

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        print "default method called for:", obj
        if isinstance(obj, complex):
            return [obj.real, obj.imag]
        return json.JSONEncoder.default(self, obj)

print json.dumps(2 + 1j, cls=ComplexEncoder)
基于此示例,我添加了GTK枚举:

import json
import gtk

ENUMS = [gtk.PAGE_ORIENTATION_PORTRAIT, gtk.PAGE_ORIENTATION_LANDSCAPE]

class GtkEncoder(json.JSONEncoder):
    def default(self, obj):
        print "default method called for:", obj
        if obj in ENUMS:
            return obj.value_name
        return json.JSONEncoder.default(self, obj)

print json.dumps(gtk.PAGE_ORIENTATION_LANDSCAPE, cls=GtkEncoder)
请注意
default
方法中添加的print语句。在最初的示例中,调用此方法没有问题,但在GTK示例中没有。
default
方法从未被调用,它返回的
当然是无效的


那么,有没有一种方法可以自动对这些枚举进行编码/解码,或者我是否仍坚持目前的手动方法?请注意,要转储的数据结构不是单个值,而是一个或多个dict。

观察到的行为之所以发生,是因为值
gtk.PAGE\u ORIENTATION\u scape
class'gtk.\u gtk.PageOrientation'
的一个实例,它继承
类型'gobject.GEnum'
,然后又继承
类型'int'

因此,GTK枚举是int,json代码假定它可以处理int,因此不调用编码器的
default
方法

不幸的是,当前的json实现在编码这样的子类类型方面没有太大帮助:-/没有继承和重写使这成为可能(至少我找不到任何解决方案)。只是在太多硬编码的位置检查值的值
isinstance(value,(int,long))

但是您当然可以修补json编码器的源代码以实现您的目标,而无需重新实现整个json功能。为此,将json库中的文件
encoder.py
(对我来说,这是
/usr/lib/python2.7/json/encoder.py
)复制到您的工作目录中,并对其进行修补

在函数
\u iterencode\u list()
\u iterencode\u dict()
(它们是函数
\u make\u iterencode()
的本地函数)中,您可以找到类型为
int
long
的检查;如果是这样,当前实现只调用
str(value)
。将其更改为
encodeInt(value)
(在三个位置!),并在
encoder.py中实现您自己的
encodeInt()
函数:

def encodeInt(value):
  try:
    return value.value_name
  except:
    return str(value)
然后,在原始代码中,您必须直接导入该修补文件:

import encoder
您必须确保不再使用C实现,而是使用补丁代码。(您可以看到,通常使用的是(更快的)C实现,而我们在其中修补的Python代码不是。)要实现这一点,只需在导入后添加:

encoder.c_make_encoder = None
现在可以使用您的补丁编码器:

print encoder.JSONEncoder().encode({
  gtk.PAGE_ORIENTATION_PORTRAIT: [
    gtk.PAGE_ORIENTATION_LANDSCAPE
  ],
  gtk.PAGE_ORIENTATION_LANDSCAPE: gtk.PAGE_ORIENTATION_PORTRAIT })
印刷品:

{"GTK_PAGE_ORIENTATION_PORTRAIT": [GTK_PAGE_ORIENTATION_LANDSCAPE], "GTK_PAGE_ORIENTATION_LANDSCAPE": GTK_PAGE_ORIENTATION_PORTRAIT}
请注意,Json dict键始终必须是字符串。这就是为什么将值用作键时会得到双引号。但即使是普通的
int
s-当用作键时-共享也是如此。它们也会被严格化


您可以查看所有源代码。

我找到了一个解决方案,虽然这可能不适用于gtk,但它通常适用于枚举

如果您可以使用IntEnum而不是Enum,那么您可以在Enum类中重写str,以返回任何您想要的字符串,最有可能的是名称或值

import json
from enum import IntEnum

class TrekCaptains(IntEnum):
    Kirk  = 0
    Picard = 1

    def __str__(self):
        return '{0}'.format(self.value)


s = {TrekCaptains.Kirk:'Original Series',
     TrekCaptains.Picard:'Next Generation'}
j = json.dumps(s)
print j

#result
#{"0": "Original Series", "1": "Next Generation"}

谢谢你的继承暗示,我真的以为会是这样的。不幸的是,只有在对枚举进行编码时,这才起作用。将枚举放入列表或dict时,
encode
arg就是整个对象,因此它失败。Urgs。好的,我认为
encode
例程是递归的。我去看看能不能把我的解决办法修好。json内部代码并不容易实现这一点。我知道了,但在接下来的20个小时内我不会有任何想法。谢谢你的调查。我花了很多时间在这上面,但找不到内置的解决方案。我已经更新了我的答案。不幸的是,这消息并不好。我看到的唯一解决方案是修补json库。详见答案。