使用 Gson 序列化 Objectify 键

发布于 2024-11-28 20:08:26 字数 4447 浏览 2 评论 0原文

有没有人能够使用具有 Key (对象化)字段的 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)

Has anyone been able to serialize/deserialize objects using gson which have Key (the objectify ones) fields?

I'm trying to use gson to do so but it seems several people online have had issues serializing appengine keys. Any tips?

When I attempt to do so I get the following error on deserialization:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼波传意 2024-12-05 20:08:26

我将其作为我的一个项目中备份套件的一部分完成。现在它对我来说绝对有效。

尝试通过其构建器对 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. 在 Key 对象中也序列化了 GAE 应用程序
    标识符。但可以通过key后反射来改变
    如果需要,可以在反序列化方法中检索。可能需要
    将数据从第一个 GAE 应用程序移动到另一个应用程序时。为我,
    键中的应用程序标识符现在为空。如果不是为了你,
    联系我。我将发布适当的代码。

  2. 此代码也适用于较旧的 Gson。如果使用 2.1,则 TypeAdapter
    子类化会更好&更快的方式。它非常类似于
    这段代码你需要实现2个方法。但这个解决方案
    也适用于旧版本。

I have it done as part of the backup suite in one my project. It definitely WORKS for me now.

Try specialization of Gson (de)serializer object by its builder:

/** 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 */
   }
 }

Final usage in code:

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

For completeness:

  1. In the Key object there is serialized also GAE application
    identificator. But it can be changed by reflection after key
    retrieval in deserialization method, if needed. It may be required
    when moving the data from the 1st GAE app to another one. For me,
    the app identificator in keys are null right now. If not for you,
    contact me. I will publish appropriate code.

  2. This code works for older Gson also. If using 2.1, the TypeAdapter
    subclassing would be better & faster way. It is quite similar to
    this code and you need to implement 2 methods. But this solution
    just works with also older versions.

若水微香 2024-12-05 20:08:26

我只需使用 Objectify 的内置 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),只需将类型从 更改为 < 即可解决/代码>。

但是,如果您需要序列化原始低级 Key 对象,则上述答案中提到的方法现在位于 KeyFactory 中而不是 Key 上。您仍然会遇到麻烦,因为 AppIdNamespace 是暂时的、私有的,并且没有方法可以在反序列化后的键上设置这些字段。

I was able to solve this problem by simply using Objectify's built-in DAOBase.fact().stringToKey() and DAOBase.fact().keyToString() methods.

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

My own problems arose from having to compile under Java 6, because I had been using Key<?> entityKey = new DAO().fact().stringToKey(serializedKey), which was solved by simply changing the type from <?> to <Entity>.

If, however, you need to serialize the raw low-level Key objects, the methods mentioned in the above answer are now located in KeyFactory instead of on Key. You will still have trouble because AppIdNamespace is transient, private, and there are no methods to set those fields on the key post-deserialization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文