Index: pyamf/adapters/_google_appengine_ext_db.py
===================================================================
--- pyamf/adapters/_google_appengine_ext_db.py	(revision 1570)
+++ pyamf/adapters/_google_appengine_ext_db.py	(working copy)
@@ -26,11 +26,8 @@
         remove = True
         self.context.class_aliases[obj.__class__] = pyamf.ClassAlias(obj.__class__, None)
 
-    self.writeObject(obj, *args, **kwargs)
+    writeObjectAMF(self, obj, args, kwargs, remove)
 
-    if remove:
-        self.context.class_aliases[obj.__class__] = None
-
 def writeObjectAMF3(self, obj, *args, **kwargs):
     try:
         self.context.getClassDefinitionReference(obj)
@@ -44,8 +41,18 @@
             alias = pyamf.ClassAlias(obj.__class__, None)
             self.context.class_aliases[obj.__class__] = alias
 
+    writeObjectAMF(self, obj, args, kwargs, remove)
+
+def writeObjectAMF(self, obj, args, kwargs, remove):
+    """
+    Writes an object that has already been prepared by writeObjectAMF0 or writeObjectAMF3.
+    """
+    try:
+        obj._key = str(obj.key())
+    except:
+        obj._key = None
     self.writeObject(obj, *args, **kwargs)
-
+    del obj._key
     if remove:
         self.context.class_aliases[obj.__class__] = None
 
@@ -53,13 +60,13 @@
     """
     Returns a list of properties on an C{db.Model} instance.
     """
-    return list(obj.__class__._properties)
+    return list(obj.__class__._properties) + ['_key']
 
 def get_attrs_for_expando(obj):
     """
     Returns a list of dynamic properties on a C{db.Expando} instance.
     """
-    return obj.dynamic_properties()
+    return obj.dynamic_properties() + ['_key']
 
 pyamf.register_class(db.Model, attr_func=get_attrs_for_model, metadata=['dynamic'])
 pyamf.register_class(db.Expando, attr_func=get_attrs_for_expando, metadata=['dynamic'])
Index: pyamf/tests/adapters/test_google.py
===================================================================
--- pyamf/tests/adapters/test_google.py	(revision 1570)
+++ pyamf/tests/adapters/test_google.py	(working copy)
@@ -32,17 +32,17 @@
 
         encoder.writeElement(jessica)
         self.assertEquals(encoder.stream.getvalue(),
-            '\x03\x00\x10weight_in_pounds\x00@\x14\x00\x00\x00\x00\x00\x00'
-            '\x00\x04type\x02\x00\x03cat\x00\x04name\x02\x00\x07Jessica\x00'
-            '\tbirthdate\x0bB^\xc4\xae\xaa\x00\x00\x00\x00\x00\x00\x12'
-            'spayed_or_neutered\x01\x00\x00\x00\t')
+            '\x03\x00\x04name\x02\x00\x07Jessica\x00\x04_key\x05\x00'
+            '\tbirthdate\x0bB^\xc4\xae\xaa\x00\x00\x00\x00\x00\x00\x10'
+            'weight_in_pounds\x00@\x14\x00\x00\x00\x00\x00\x00\x00\x04'
+            'type\x02\x00\x03cat\x00\x12spayed_or_neutered\x01\x00\x00\x00\t')
 
         encoder = pyamf.get_encoder(pyamf.AMF3)
         encoder.writeElement(jessica)
         self.assertEquals(encoder.stream.getvalue(),
-            '\n\x0b\x01!weight_in_pounds\x04\x05\ttype\x06\x07cat\tname\x06'
-            '\x0fJessica\x13birthdate\x08\x01B^\xc4\xae\xaa\x00\x00\x00%'
-            'spayed_or_neutered\x02\x01')
+            '\n\x0b\x01\tname\x06\x0fJessica\t_key\x01\x13birthdate'
+            '\x08\x01B^\xc4\xae\xaa\x00\x00\x00!weight_in_pounds'
+            '\x04\x05\ttype\x06\x07cat%spayed_or_neutered\x02\x01')
 
     def test_expando(self):
         # 'borrowed' from http://code.google.com/appengine/docs/datastore/entitiesandmodels.html
@@ -63,17 +63,19 @@
 
         encoder.writeElement(jessica)
         self.assertEquals(encoder.stream.getvalue(),
-            '\x03\x00\x04name\x02\x00\x07Jessica\x00\tbirthdate\x0bB^\xc4\xae'
-            '\xaa\x00\x00\x00\x00\x00\x00\x10weight_in_pounds\x00@\x14\x00'
-            '\x00\x00\x00\x00\x00\x00\x03foo\x02\x00\x03bar\x00\x04type\x02'
-            '\x00\x03cat\x00\x12spayed_or_neutered\x01\x00\x00\x00\t')
+            '\x03\x00\x04name\x02\x00\x07Jessica\x00\x04_key\x05\x00'
+            '\tbirthdate\x0bB^\xc4\xae\xaa\x00\x00\x00\x00\x00\x00\x10'
+            'weight_in_pounds\x00@\x14\x00\x00\x00\x00\x00\x00\x00\x03'
+            'foo\x02\x00\x03bar\x00\x04type\x02\x00\x03cat\x00\x12'
+            'spayed_or_neutered\x01\x00\x00\x00\t')
 
         encoder = pyamf.get_encoder(pyamf.AMF3)
         encoder.writeElement(jessica)
         self.assertEquals(encoder.stream.getvalue(),
-            '\n\x0b\x01\tname\x06\x0fJessica\x13birthdate\x08\x01B^\xc4\xae'
-            '\xaa\x00\x00\x00!weight_in_pounds\x04\x05\x07foo\x06\x07bar\t'
-            'type\x06\x07cat%spayed_or_neutered\x02\x01')
+            '\n\x0b\x01\tname\x06\x0fJessica\t_key\x01\x13birthdate'
+            '\x08\x01B^\xc4\xae\xaa\x00\x00\x00!weight_in_pounds'
+            '\x04\x05\x07foo\x06\x07bar\ttype\x06\x07'
+            'cat%spayed_or_neutered\x02\x01')
 
 
 def suite():
