InvalidProtocolBufferException 总是在 BatchAnnotateImagesResponse.parseFrom() 上抛出

InvalidProtocolBufferException always thrown on BatchAnnotateImagesResponse.parseFrom()

我正在尝试使用 Google Cloud Vision 的 API。到目前为止,我已经成功发出请求并以 json 格式接收所需数据。问题在于将该响应解析为我可以使用的模型 class。

request,responseparsing是同一个方法:

要求:

private static BatchAnnotateImagesResponse clientImageRequest(String contenidoImagen) {             
        BatchAnnotateImagesResponse sol = BatchAnnotateImagesResponse.getDefaultInstance();

        log.log(Level.FINEST, "Procesando la imagen del cliente");
        try {

            log.log(Level.FINE, "Creando conexion");
            URL serverUrl = new URL(TARGET_URL + API_KEY); //previously declared constants
            URLConnection urlConnection = serverUrl.openConnection();
            HttpURLConnection httpConnection = (HttpURLConnection)urlConnection;

            httpConnection.setRequestMethod("POST");
            httpConnection.setRequestProperty("Content-Type", "application/json");
            httpConnection.setConnectTimeout(60000);
            httpConnection.setReadTimeout(60000);

            httpConnection.setDoOutput(true);

            log.log(Level.FINE, "Creando peticion");
            BufferedWriter httpRequestBodyWriter = new BufferedWriter(new OutputStreamWriter(httpConnection.getOutputStream()));
            httpRequestBodyWriter.write(
                    "{\"requests\": [{ \"features\": [ { \"maxResults\": 10, \"type\": \"WEB_DETECTION\" } ], \"image\": { \"content\": \""+contenidoImagen+"\" } } ] }");
            httpRequestBodyWriter.close();

            log.log(Level.INFO, "BufferedWriter de la peticion cerrado correctamente");

正如我所说,这部分进行得很顺利。


回复:

log.log(Level.FINE, "Obteniendo la respuesta");
            InputStream respuesta = httpConnection.getInputStream();

            if (respuesta == null) {
                log.log(Level.SEVERE, "No hay InputStream");
                throw new NullPointerException("InputStream nulo");
            }else {
                log.log(Level.FINEST, "La respuesta se ha recibido correctamente");

                //sol = BatchAnnotateImagesResponse.parseFrom(respuesta);  this throws IOException

                Scanner httpResponseScanner = new Scanner (respuesta);
                StringBuilder resp = new StringBuilder("");
                while (httpResponseScanner.hasNext()) {
                    String line = httpResponseScanner.nextLine();
                    resp.append(line);
                    log.log(Level.INFO, line);

                    if(httpResponseScanner.hasNext()) {
                        resp.append("\n");
                    }
                }
                log.log(Level.INFO, "Respuesta al completo: \n"+resp.toString());
                httpResponseScanner.close();
                log.log(Level.FINE, "Scanner cerrado correctamente");

正如您在日志中看到的,我打印了 resp.toString(),并且它 returns 对应 body 我介绍的图像的响应。例如,建筑物(由于 SOF 最大 body 个字符,我不得不缩短它):

[INFO] GCLOUD: {
[INFO] GCLOUD:   "responses": [
[INFO] GCLOUD:     {
[INFO] GCLOUD:       "webDetection": {
[INFO] GCLOUD:         "webEntities": [
[INFO] GCLOUD:             "url": "http://passionbythetravel.com/top-10-tallest-buildings-in-spain/",
[INFO] GCLOUD:             "pageTitle": "Top 10 Tallest Buildings in Spain » Passion by the Travel",
[INFO] GCLOUD:             "partialMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "http://passionbythetravel.com/wp-content/uploads/2019/10/Torre-Sevilla.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://votefrankharris.com/image/savanaspringarn",
[INFO] GCLOUD:             "pageTitle": "Savanaspringarn - Vote Frank Harris",
[INFO] GCLOUD:             "partialMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/274px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://es.wikipedia.org/wiki/Torre_Sevilla",
[INFO] GCLOUD:             "pageTitle": "Torre \u003cb\u003eSevilla\u003c/b\u003e - Wikipedia, la enciclopedia libre",
[INFO] GCLOUD:             "fullMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/1200px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/250px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/a/aa/Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://moovitapp.com/index/en/public_transit-Torre_Sevilla-Sevilla-site_14527821-3802",
[INFO] GCLOUD:             "pageTitle": "How to get to Torre \u003cb\u003eSevilla\u003c/b\u003e in \u003cb\u003eSevilla\u003c/b\u003e by Bus, Train or Metro | Moovit",
[INFO] GCLOUD:             "partialMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/274px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://es.m.wikipedia.org/wiki/Archivo:Torre_Sevilla_2017.jpg",
[INFO] GCLOUD:             "pageTitle": "Archivo:Torre \u003cb\u003eSevilla\u003c/b\u003e 2017.jpg - Wikipedia, la enciclopedia libre",
[INFO] GCLOUD:             "fullMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/1200px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/321px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/513px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/a/aa/Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/401px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/160px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/684px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://es.wikipedia.org/wiki/Archivo:Torre_Sevilla_2017.jpg",
[INFO] GCLOUD:             "pageTitle": "Archivo:Torre \u003cb\u003eSevilla\u003c/b\u003e 2017.jpg - Wikipedia, la enciclopedia libre",
[INFO] GCLOUD:             "fullMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/1200px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/321px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/513px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/a/aa/Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/401px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/160px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               },
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/684px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://moovitapp.com/index/es/transporte_p%C3%BAblico-Torre_Sevilla-Sevilla-site_14527821-3802",
[INFO] GCLOUD:             "pageTitle": "Cómo llegar a Torre \u003cb\u003eSevilla\u003c/b\u003e en \u003cb\u003eSevilla\u003c/b\u003e en Autobús, Tren o Metro ...",
[INFO] GCLOUD:             "partialMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Torre_Sevilla_2017.jpg/274px-Torre_Sevilla_2017.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://www.instantoffices.com/es/es/alquiler-de-oficinas/sevilla/estadio-ol%C3%ADmpico-de-la-cartuja-34910",
[INFO] GCLOUD:             "pageTitle": "Oficinas: Estadio Olímpico de la Cartuja, \u003cb\u003eSeville\u003c/b\u003e, 41092 | Oficinas ...",
[INFO] GCLOUD:             "fullMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://content.instantoffices.com/sc/Prod/images/centres/212width/50161/50161-377239.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://www.instantoffices.com/es/es/alquiler-de-oficinas/sevilla/paseo-de-las-delicias-12434",
[INFO] GCLOUD:             "pageTitle": "Oficinas: Paseo de las Delicias, \u003cb\u003eSeville\u003c/b\u003e, 41001 | Oficinas ...",
[INFO] GCLOUD:             "fullMatchingImages": [
[INFO] GCLOUD:               {
[INFO] GCLOUD:                 "url": "https://content.instantoffices.com/sc/Prod/images/centres/212width/50161/50161-377239.jpg"
[INFO] GCLOUD:               }
[INFO] GCLOUD:             ]
[INFO] GCLOUD:           }
[INFO] GCLOUD:         ],
[INFO] GCLOUD:         "visuallySimilarImages": [
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://sevillasecreta.co/wp-content/uploads/2017/08/Torre_Sevilla_abril_2015.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://archivos.wikanda.es/sevillapedia/thumb/Torre_Cajasol_%28Sevilla%29.jpg/280px-Torre_Cajasol_%28Sevilla%29.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://media-cdn.tripadvisor.com/media/photo-s/09/49/9f/7b/cajasol-tower.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://m.eldiario.es/andalucia/Torre-Sevilla_EDIIMA20160217_0512_18.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://www.torre-sevilla.com/wp-content/uploads/2017/02/imagen_3.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "http://i.imgur.com/PSpQZER.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://media-cdn.tripadvisor.com/media/photo-s/0a/a1/a3/e3/cajasol-tower.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "http://1.bp.blogspot.com/-D0B9SCQUh2o/Vak22borOWI/AAAAAAAADn4/H9YFAkUbvAk/s1600/esp179.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "https://static1-sevilla.abc.es/Media/201501/30/torre-pelli-sevilla--644x362.jpg"
[INFO] GCLOUD:           },
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "url": "http://i.imgur.com/GSdKmVp.jpg"
[INFO] GCLOUD:           }
[INFO] GCLOUD:         ],
[INFO] GCLOUD:         "bestGuessLabels": [
[INFO] GCLOUD:           {
[INFO] GCLOUD:             "label": "pintalabios sevilla",
[INFO] GCLOUD:             "languageCode": "es"
[INFO] GCLOUD:           }
[INFO] GCLOUD:         ]
[INFO] GCLOUD:       }
[INFO] GCLOUD:     }
[INFO] GCLOUD:   ]
[INFO] GCLOUD: }

正在解析:

                log.log(Level.FINE, "Convirtiendo string de respuesta a modelo");
                sol = BatchAnnotateImagesResponse.parseFrom(ByteBuffer.wrap(resp.toString().getBytes()));//The code explodes here

            }

        }catch(MalformedURLException e1) {
            log.log(Level.SEVERE, "La URL se ha formado incorrectamente"+ Arrays.toString(e1.getStackTrace()));
        }catch(IOException e2) {
            log.log(Level.SEVERE, "Problema en la lectura/escritura de los datos\n"+e2.toString()+"\n"+Arrays.toString(e2.getStackTrace()));
        }catch(Exception e3) {
            log.log(Level.SEVERE, "Algo ha pasado durante el procesamiento de la imagen: "+ Arrays.toString(e3.getStackTrace()));
        }

        return sol;

    }


错误:

[INFO] GCLOUD: SEVERE: Problema en la lectura/escritura de los datos
[INFO] GCLOUD: com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
[INFO] GCLOUD: [com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:106), com.google.protobuf.CodedInputStream$ArrayDecoder.checkLastTagWas(CodedInputStream.java:635), com.google.protobuf.CodedInputStream$ArrayDecoder.readGroup(CodedInputStream.java:834), com.google.protobuf.UnknownFieldSet$Builder.mergeFieldFrom(UnknownFieldSet.java:548), com.google.protobuf.GeneratedMessageV3.parseUnknownField(GeneratedMessageV3.java:320), com.google.cloud.vision.v1.BatchAnnotateImagesResponse.<init>(BatchAnnotateImagesResponse.java:89), com.google.cloud.vision.v1.BatchAnnotateImagesResponse.<init>(BatchAnnotateImagesResponse.java:30), com.google.cloud.vision.v1.BatchAnnotateImagesResponse.parsePartialFrom(BatchAnnotateImagesResponse.java:934), com.google.cloud.vision.v1.BatchAnnotateImagesResponse.parsePartialFrom(BatchAnnotateImagesResponse.java:928), com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:134), com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:149), com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:48), com.google.cloud.vision.v1.BatchAnnotateImagesResponse.parseFrom(BatchAnnotateImagesResponse.java:257), aiss.controller.WebDetectionController.clientImageRequest(WebDetectionController.java:103), aiss.controller.WebDetectionController.imageToModel(WebDetectionController.java:123), org.apache.jsp.web_002ddetection_jsp._jspService(web_002ddetection_jsp.java:129), org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70), javax.servlet.http.HttpServlet.service(HttpServlet.java:790), org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476), org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386), org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330), com.google.appengine.tools.development.jetty9.PrivilegedJspServlet.access1(PrivilegedJspServlet.java:21), com.google.appengine.tools.development.jetty9.PrivilegedJspServlet.run(PrivilegedJspServlet.java:75), java.base/java.security.AccessController.doPrivileged(Native Method), com.google.appengine.tools.development.jetty9.PrivilegedJspServlet.service(PrivilegedJspServlet.java:71), javax.servlet.http.HttpServlet.service(HttpServlet.java:790), org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1395), org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617), com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366), com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349), com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.DevAppServerRequestLogFilter.doFilter(DevAppServerRequestLogFilter.java:28), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545), org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143), org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:608), org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127), org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235), org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610), org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233), org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1300), org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188), org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485), org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580), org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186), org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1215), com.google.appengine.tools.development.jetty9.DevAppEngineWebAppContext.doScope(DevAppEngineWebAppContext.java:94), org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141), org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:220), org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:79), aiss.ImageServlet.doGet(ImageServlet.java:65), aiss.ImageServlet.doPost(ImageServlet.java:91), javax.servlet.http.HttpServlet.service(HttpServlet.java:707), javax.servlet.http.HttpServlet.service(HttpServlet.java:790), org.eclipse.jetty.servlet.ServletHolder$NotAsyncServlet.service(ServletHolder.java:1395), org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617), com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:134), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:48), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.jetty9.StaticFileFilter.doFilter(StaticFileFilter.java:123), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366), com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349), com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604), com.google.appengine.tools.development.DevAppServerRequestLogFilter.doFilter(DevAppServerRequestLogFilter.java:28), org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1596), org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545), org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143), org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566), org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127), org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235), org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610), org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233), org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1300), org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188), org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485), org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580), org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186), org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1215), com.google.appengine.tools.development.jetty9.DevAppEngineWebAppContext.doScope(DevAppEngineWebAppContext.java:94), org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141), org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127), com.google.appengine.tools.development.jetty9.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:610), org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127), org.eclipse.jetty.server.Server.handle(Server.java:500), org.eclipse.jetty.server.HttpChannel.lambda$handle(HttpChannel.java:383), org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547), org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375), org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273), org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311), org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103), org.eclipse.jetty.io.ChannelEndPoint.run(ChannelEndPoint.java:117), org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806), org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938), java.base/java.lang.Thread.run(Thread.java:834)]

我已经尝试了 parseFrom() 的所有变体,但它 总是 抛出 InvalidProtocolBufferException 而我无法通过它。怎么了?

正如 Tom Cools 在评论中所说,解决这个问题最快(也许不是最好)的方法是使用特定的库来读取 JSON 而不是在 Vision 的客户端库上使用的 Protocol Buffers API。

我使用 jsonschema2pojo 生成 Java classes 使用我在问题上展示的 resp.toString() 来生成它们。

作为最后一步,我使用 Gson 创建了在 jsonchema2pojo 中生成的主要 class 实例:

Gson json = new Gson();
VisionResponse imagenes = json.fromJson(contenido, VisionResponse.class);

我本来想使用 API 的客户端库,但这确实有用。