Protobuf: Fail to printAny with JsonFormat in Java. com.google.protobuf.InvalidProtocolBufferException: Cannot find type for url: type.googleapis.com/api.DataEntity.

Created on 29 Aug 2019  路  1Comment  路  Source: protocolbuffers/protobuf

Version: libprotoc 3.7.1
Language: Java 1.8.0_201
Operating system: Mac 10.14.6


I try to printAny, but get InvalidProtocolBufferException Exception in thread "main" com.google.protobuf.InvalidProtocolBufferException: Cannot find type for url: type.googleapis.com/api.DataEntity. All of the relevant codes are shown following.

package com.bees360.internal.ai.grpc.proto;

import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import io.gitlab.donespeak.protobuf.DataProto;
import io.gitlab.donespeak.protobuf.ResponseTestProto;

/**
 * @author DoneSpeak
 * @date 2019/08/29 10:22
 */
public class ResponseJsonTest {

    public static void main(String[] args) throws InvalidProtocolBufferException {
        DataProto.DataEntity data = DataProto.DataEntity.newBuilder().setData("data ...").build();

        ResponseTestProto.ResponseJson.Builder builder = ResponseTestProto.ResponseJson.newBuilder();

        builder.setData(Any.pack(data));

        System.out.println(JsonFormat.printer().print(data));

        ResponseTestProto.ResponseJson json = builder.build();

        DataProto.DataEntity stageData = json.getData().unpack(DataProto.DataEntity.class);

        System.out.println(json.getData().getTypeUrl());
        // Exception
        System.out.println(JsonFormat.printer().print(json.getData()));

        System.out.println(stageData);
       // Exception
        System.out.println(JsonFormat.printer().print(json));
    }
}

DataProto.proto

syntax = "proto3";

option java_package = "io.gitlab.donespeak.protobuf";
package api;

message DataEntity {
    string data = 1;
}

ResponseTestProto.proto

syntax = "proto3";

import "google/protobuf/any.proto";

option java_package = "io.gitlab.donespeak.protobuf";
package api;

message ResponseJson {
    int32 code = 1;
    string msg = 2;
    google.protobuf.Any data = 3;
}

Exception

{
  "data": "data ..."
}
type.googleapis.com/api.DataEntity
Exception in thread "main" com.google.protobuf.InvalidProtocolBufferException: Cannot find type for url: type.googleapis.com/api.DataEntity
    at com.google.protobuf.util.JsonFormat$PrinterImpl.printAny(JsonFormat.java:810)
    at com.google.protobuf.util.JsonFormat$PrinterImpl.access$1000(JsonFormat.java:643)
    at com.google.protobuf.util.JsonFormat$PrinterImpl$1.print(JsonFormat.java:713)
    at com.google.protobuf.util.JsonFormat$PrinterImpl.print(JsonFormat.java:692)
    at com.google.protobuf.util.JsonFormat$Printer.appendTo(JsonFormat.java:332)
    at com.google.protobuf.util.JsonFormat$Printer.print(JsonFormat.java:342)
    at com.bees360.internal.ai.grpc.proto.ResponseJsonTest.main(ResponseJsonTest.java:30)

Process finished with exit code 1

Most helpful comment

I solve the problem. A TypeRegistry for Any field is required.

A TypeRegistry is used to resolve Any messages in the JSON conversion. You must provide a TypeRegistry containing all message types used in Any message fields, or the JSON conversion will fail because data in Any message fields is unrecognizable. You don鈥檛 need to supply a TypeRegistry if you don鈥檛 use Any message fields.

Class JsonFormat.TypeRegistry @JavaDoc

JsonFormat.TypeRegistry typeRegistry = JsonFormat.TypeRegistry.newBuilder()
    .add(DataProto.DataEntity.getDescriptor())
    .build();

JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(typeRegistry);

System.out.println(printer.print(json.getData()));
System.out.println(printer.print(json));

>All comments

I solve the problem. A TypeRegistry for Any field is required.

A TypeRegistry is used to resolve Any messages in the JSON conversion. You must provide a TypeRegistry containing all message types used in Any message fields, or the JSON conversion will fail because data in Any message fields is unrecognizable. You don鈥檛 need to supply a TypeRegistry if you don鈥檛 use Any message fields.

Class JsonFormat.TypeRegistry @JavaDoc

JsonFormat.TypeRegistry typeRegistry = JsonFormat.TypeRegistry.newBuilder()
    .add(DataProto.DataEntity.getDescriptor())
    .build();

JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(typeRegistry);

System.out.println(printer.print(json.getData()));
System.out.println(printer.print(json));
Was this page helpful?
0 / 5 - 0 ratings