2

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)
4

2 に答える 2

2

私のプロジェクトのバックアップスイートの一部としてそれを行いました。それは今私にとって間違いなく機能します。

ビルダーによる Gson (de)serializer オブジェクトの特殊化を試してください。

/** 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 アプリケーション ID もシリアライズされています。ただし、必要に応じて、デシリアライズ メソッドでのキー取得後にリフレクションによって変更できます。最初の GAE アプリから別の GAE アプリにデータを移動するときに必要になる場合があります。私にとって、キーのアプリ識別子は現在 null です。あなたのためではない場合は、私に連絡してください。適切なコードを公開します。

  2. このコードは、古い Gson でも機能します。2.1 を使用している場合は、TypeAdapter のサブクラス化がより優れた高速な方法になります。これはこのコードとよく似ており、2 つのメソッドを実装する必要があります。ただし、このソリューションは古いバージョンでも機能します。

于 2012-08-20T09:44:50.457 に答える
0

DAOBase.fact().stringToKey()この問題は、Objectify の組み込みメソッドとメソッドを使用するだけで解決できました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 オブジェクトをシリアル化する必要がある場合、上記の回答で言及されているメソッドは、Key ではなく KeyFactory に配置されます。AppIdNamespace は一時的で非公開であり、デシリアライゼーション後のキーにこれらのフィールドを設定する方法がないため、まだ問題があります。

于 2013-12-03T17:18:53.260 に答える