2011-08-09 66 views
2

有人能夠使用具有Key(objectify的)字段的gson序列化/反序列化對象嗎?序列化使用Gson的物化鍵

我想使用gson來這樣做,但它似乎在網上有幾個人有序列化appengine鍵的問題。有小費嗎?

當我試圖這樣做,我得到的反序列化以下錯誤:

java.lang.NullPointerException 
    at com.google.appengine.api.datastore.KeyTranslator.convertToPb(KeyTranslator.java:55) 
    at com.google.appengine.api.datastore.DataTypeTranslator$ReferenceType.setPropertyValue(DataTypeTranslator.java:680) 
    at com.google.appengine.api.datastore.DataTypeTranslator.createPropertyValue(DataTypeTranslator.java:207) 
    at com.google.appengine.api.datastore.DataTypeTranslator.createProperty(DataTypeTranslator.java:191) 
    at com.google.appengine.api.datastore.DataTypeTranslator.addProperty(DataTypeTranslator.java:159) 
    at com.google.appengine.api.datastore.DataTypeTranslator.addPropertiesToPb(DataTypeTranslator.java:142) 
    at com.google.appengine.api.datastore.EntityTranslator.convertToPb(EntityTranslator.java:47) 
    at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.doBatchPutBySize(AsyncDatastoreServiceImpl.java:475) 
    at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.put(AsyncDatastoreServiceImpl.java:446) 
    at com.googlecode.objectify.impl.AsyncObjectifyImpl.put(AsyncObjectifyImpl.java:255) 
    at com.googlecode.objectify.impl.AsyncObjectifyImpl.put(AsyncObjectifyImpl.java:229) 
    at com.googlecode.objectify.impl.ObjectifyImpl.put(ObjectifyImpl.java:126) 
    at com.rewardly.mailfoo.dataaccess.DAO.storeEntity(DAO.java:36) 
    at com.rewardly.mailfoo.ajaxcalls.UpdateEntity.doPost(UpdateEntity.java:38) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
    at com.rewardly.mailfoo.utils.UserFilter.doFilter(UserFilter.java:44) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) 
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
    at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:351) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at org.mortbay.jetty.Server.handle(Server.java:326) 
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) 
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) 
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 
+0

這有助於查看com.rewardly.mailfoo.ajaxcalls.UpdateEntity.doPost以及它正在處理的JSON格式。 –

+0

不知道它是否可以完成(希望別人可以提出解決方法),但如果不能,你可以檢查Jackson。一些用戶已經在努力獲得Objectify密鑰的工作(我假設成功,應該很容易驗證)。 – StaxMan

回答

2

我已經完成它作爲一個我的項目備份套件的一部分。它現在對我來說絕對有效。 GSON(反)序列化對象的

嘗試專門通過它的建造者:

/** Helper class for deserialization of Key 
    * @copyright TrashOut, s.r.o. 2012 */ 
@SuppressWarnings("rawtypes") 
public static class KeyAdapterSerializer implements JsonSerializer<Key>, JsonDeserializer<Key>, InstanceCreator<Key> { 
    @Override 
    public JsonElement serialize(Key key, Type type, JsonSerializationContext serialContext) { 
    return new JsonPrimitive(key.getString()); 
    } 
    @Override 
    public Key deserialize(JsonElement element, Type type, 
     JsonDeserializationContext deserialContext) throws JsonParseException { 
    Misc.log.warning(" element content " + element.getAsString()); 
    return Key.create(element.getAsString()); 
    } 
    @Override 
    public Key createInstance(Type type) { 
    Misc.log.warning(" element content " + type.getClass()); 
    return Key.create(BlahBlah.class, 1L); 
/* FIXME: BlahBlah is ANY class storable by your Objectify = registred in DAO 
* (extending DAOBase; registered by OjectifyService.register(clazz) method) ; 
* This MUST return any existing Key -that class has NO nullary constructor; we 
* will change the key immediately after in deserialize method */ 
    } 
} 

最終用途代碼:

public static Gson gson = (new GsonBuilder()).serializeNulls() 
.setPrettyPrinting().registerTypeAdapter(Key.class, new KeyAdapterSerializer()).create(); 
// creating Gson instance which will serialize all and prints nicely 
// --> turn off setPrettyPrinting() for performance improvement 
// see http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html 
// for more preferences 

String myObjectJsonStringRepresentation =gson.toJson(myObject); 
// in String you have string representation of the all object -WITH THE KEY 

出於完整性:

  1. 在重點對象還有系列化的GAE應用識別器。但是如果需要,可以通過在反序列化方法中鍵 檢索之後的反射來改變它。將數據從第1個GAE應用移至另一個應用時,可能需要 。對於我來說, 密鑰中的應用標識符現在爲空。如果不適合你, 與我聯繫。我將發佈適當的代碼。

  2. 此代碼也適用於較老的Gson。如果使用2.1,TypeAdapter 的子類化將更好的方式更好地&。這個代碼非常類似於 ,您需要實現2個方法。但是這個解決方案 只適用於老版本。

0

我可以簡單地使用物化的內置DAOBase.fact().stringToKey()DAOBase.fact().keyToString()的方法來解決這個問題。

String serializedKey = new DAO().fact().keyToString(entity.getKey()); 
     ... 
Key<Entity> entityKey = new DAO().fact().stringToKey(serializedKey); 

我自己的問題,從具有Java 6的下編譯出現了,因爲我一直在使用Key<?> entityKey = new DAO().fact().stringToKey(serializedKey),這是通過簡單地改變類型從<?><Entity>解決。

但是,如果您需要序列化原始低級別Key對象,則上述答案中提到的方法現在位於KeyFactory中而不是Key上。您仍然會遇到麻煩,因爲AppIdNamespace是暫時的,私有的,並且沒有方法可以在關鍵後反序列化中設置這些字段。