Python中的Javascript可枚举属性

时间:2019-06-24 19:27:23

标签: python

我有一些要用JSON表示的类

在Javascript中,如果将getter属性定义为可枚举的,则可以将其包含在Json.stringfy()中或将其排除:像这样的true / false:

class Example {

    constructor(){
        Object.defineProperties(this, {
            notEnumerableProperty: {
                get: function () {
                    return 'this is not enumerable';
                },
                enumerable: false
            },
            enumerableProperty: {
                get: function () {
                    return 'this is a enumerable';
                },
                enumerable: true
            }
        });
    }

}

const instance = new Example;

JSON.stringify(instance);
// output "{"enumerableProperty":"this is a enumerable"}"

在Python中,我们可以使用@property装饰器将getter函数定义为类似于Javascript中的属性。但是它没有在JSON中列出:

#JSONEncoder as seen in https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable
from json import JSONEncoder

class MyEncoder(JSONEncoder):
  def default(self, o):
      return o.__dict__    


#My class
class Example():

  def __init__(self):
    self.value = 'this value is enumerable'

  @property
  def enumerableProperty(self):
    return 'It cannot enumerable';

  @property
  def notEnumerableProperty(self):
    return 'It is not enumerable';

instance = Example()
toJson = MyEncoder().encode(instance)

print(toJson)
#output: {"value": "this value is enumerable"}

是否可以像在Javascript中那样将属性枚举到JSON中?

2 个答案:

答案 0 :(得分:1)

这种事情是非常“非Pythonic的”,但是您可以从创建自定义form装饰器然后拥有自定义property进行检查的过程中获得一些收获。装饰器将是这样的:

JSONEncoder

我们可以通过以下操作在编码器中进行检查:

class property_nonenum(property):
    __slots__ = {'__doc__'}

我们可以用一个虚拟类对此进行测试:

import json

class JsonObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        ignore = set()
        cls = type(obj)
        for name in dir(cls):
            if name.startswith('_'):
                continue
            x = getattr(cls, name, None)
            if callable(x):
                # don't want methods
                ignore.add(name)
            elif isinstance(x, property):
                # ignore properties that aren't enumerable
                if isinstance(x, property_nonenum):
                    ignore.add(name)
        result = {}
        for name in dir(obj):
            if name.startswith('_') or name in ignore:
                continue
            result[name] = getattr(obj, name)
        return result

这给了我:class Example: __slots__ = {'foo'} def __init__(self): self.foo = 10 @property def bar(self): return 20 @property_nonenum def baz(self): return 30 def myfn(self): return 40 myval = 50 print(json.dumps(Example(), cls=JsonObjectEncoder))

答案 1 :(得分:0)

您可以使用自定义JSON编码器(doc)并使用data1 <- na.omit(mcdf) counts <- addmargins(table(data1$type_pathogen , data1$casecontrol ), 1) barplot(counts beside = TRUE, col = c(4 ,3) , legend = data1$casecontrol) 获取类(doc)的属性:

inspect.getmembers()

打印:

import inspect
import json

class my_class:
    def __init__(self):
        self.__foo = 'Hello World!'
        self.i = 111

    @property
    def foo(self):
        return self.__foo

class MyEncoder(json.JSONEncoder):
    def default(self, o):
        properties = [(name, getattr(o, name)) for name, value in inspect.getmembers(o.__class__, lambda p: isinstance(p, property))]
        values = [(name, value) for name, value in o.__dict__.items() if not name.startswith('_')]
        return dict(properties + values)

m = my_class()
print(json.dumps(m, cls=MyEncoder))