tags:

views:

99

answers:

3

I'm creating a simple API that creates typed classes based on JSON data that has a mandatory 'type' field defined in it. It uses this string to define a new type, add the fields in the JSON object, instantiate it, and then populate the fields on the instance.

What I want to be able to do is allow for these types to be optionally pre-defined in whatever application is using my module. This is so methods and other application-specific attributes not found in the JSON object can be added. I'd like to have my module check if a type already exists, and if it does, use that instead of dynamically creating the type. It would still add attributes from the JSON object, but it would be recycling the existing type.

My JSON data is:

{
    "type": "Person",
    "firstName": "John",
    "lastName": "Smith",
    "address": {
     "streetAddress": "21 2nd Street",
     "city": "New York",
     "state": "NY",
     "postalCode": 10021
    },
    "phoneNumbers": [
     "212 555-1234",
     "646 555-4567"
    ]
}

My code so far (assume json_object is a dict at this point):

if not json_object.has_key('type'):
    raise TypeError('JSON stream is missing a "type" attribute.')

##### THIS IS WHERE I WANT TO CHECK IF THE TYPE BY THAT NAME EXISTS ALREADY ####
# create a type definition and add attributes to it
definition = type(json_object['type'], (object,), {})
for key in json_object.keys():
    setattr(definition, key, None)

# instantiate and populate a test object
tester = definition()
for key, value in json_object.iteritems():
    setattr(tester, key, value)
A: 

You can use dir():

Python 2.5.2 (r252:60911, Oct  5 2008, 19:29:17)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__builtins__', '__doc__', '__name__']
>>> class Foo:
...     pass
...
>>> dir()
['Foo', '__builtins__', '__doc__', '__name__']
>>> type(eval('Foo'))
<type 'classobj'>
Can Berk Güder
+2  A: 

If you want to reuse types that you created earlier, it's best to cache them yourself:

json_types = {}
def get_json_type(name):
  try:
    return json_types[name]
  except KeyError:
    json_types[name] = t = type(json_object['type'], (object,), {})
    # any further initialization of t here
    return t

definition = get_json_type(json_object['type'])
tester = definition()
# or: tester = get_json_type(json_object['type'])()

If you want to have them added to the module namespace, do

json_types = globals()

instead.

Martin v. Löwis
+1  A: 

You can use dir() to get a list of all the names of all objects in the current environment, and you can use globals() to a get a dictionary mapping those names to their values. Thus, to get just the list of objects which are classes, you can do:

import types
listOfClasses = [cls for cls in globals().values() if type(cls) == types.ClassType]
Adam Rosenfield