python - JSON 编码/解码 GTK 枚举

标签 python json gtk pygtk

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

许多属性都是 GTK 枚举,例如 gtk.PAGE_ORIENTATION_PORTRAIT , gtk.ANCHOR_CENTERpango.ALIGN_LEFT .它们有一个唯一的名称,可以通过 obj.value_name 检索到。获取有效的 JSON 类型。

目前我的每个元素都有两种方法:to_str()获取 value_name 和 from_str()它再次将 str 映射到枚举。我想使它自动化,这样我就不会忘记调用它们并稍微清理一下代码。 JSONEncoder 和 JSONDecodr 正是这样做的,或者我认为...

这是 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 中添加的打印语句方法。在原始示例中,调用此方法没有问题,但在 GTK 示例中则没有。 default方法从未被调用,它返回 <enum GTK_PAGE_ORIENTATION_LANDSCAPE of type GtkPageOrientation>这当然不是有效的 JSON。

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

最佳答案

出现观察到的行为是因为值 gtk.PAGE_ORIENTATION_LANDSCAPEclass 'gtk._gtk.PageOrientation' 的一个实例,它继承了 type 'gobject.GEnum' 又继承了 type 'int'

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

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

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

在函数 _iterencode_list()_iterencode_dict() 中(它们是函数 _make_iterencode() 的局部函数)你可以找到检查intlong 类型;如果是这样,当前的实现只是调用 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 字典键始终必须是字符串。这就是为什么您的值在用作键时会带有双引号。但即使是普通的 int - 当用作键时 - 也是如此。它们也会被字符串化。

你可以看看http://pastebin.com/2HAtN9E8查看所有来源。

关于python - JSON 编码/解码 GTK 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21606049/

相关文章:

c - 如何在 C 语言的 gtk3 程序中增加按钮或标签的字体大小?

c++ - 想要将 "GdkPixbuf"转换为 "GtkSelectionData"对象

python - 如何在将过滤值保持为零的同时过滤 Python 列表

python - 从 python 脚本中启动并行进程?

javascript - 将数据库中的数据格式化为 Highcharts 系列格式

java - jackson 未能反序列化简单的 JSON

Python Ncurses 打印单个字符以定位

python - 修补已修补的类的方法

javascript - 未捕获的类型错误 : Cannot use 'in' operator to search for '123' in

python - 如何在Python中的GTK组合框中选择多个项目