首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在spring-boot中将protobuf作为JSON发送

在spring-boot中将protobuf作为JSON发送
EN

Stack Overflow用户
提问于 2018-08-28 02:02:33
回答 3查看 5.4K关注 0票数 8

我正在使用protobufs和这个具体的定义。

代码语言:javascript
复制
message Hash {
    string category = 1;
    repeated KVPair content = 2;
}

message KVPair {
    string key = 1;
    string value = 2;
}

我想将此作为JSON与我的spring-boot应用程序一起发送。我将这个包添加到我的gradle依赖项中:

代码语言:javascript
复制
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.6.1'

当我尝试使用以下代码输出Hash生成的对象时:

代码语言:javascript
复制
@RestController
@RequestMapping("/api/crm/")
public class KVController {

    private final KVService kvService;

    public KVController(KVService kvService) {
        this.kvService = kvService;
    }

    @GetMapping("kv/{category}")
    public Hash getHash(@PathVariable String category) {
        Hash hash = kvService.retrieve(category);
        return hash;
    }
}

它抛出了这个终极异常:

数据库由: com.fasterxml.jackson.databind.exc.InvalidDefinitionException:直接自引用导致循环(通过引用链: com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~jackson-

-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191) ~jackson--2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:944) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:721) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.数据库(BeanSerializerBase.java:719) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~jackson-serializeFields-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind。ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396) ~jackson-databind-2.9.6.jar:2.9.6 at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:913) ~jackson-databind-2.9.6.jar:2.9.6 at org.springframework.http.converter.json

kvService只从redis返回数据。它将散列数据类型(https://redis.io/topics/data-types)解析为proto中定义的散列对象。我不能显示所有的源代码,因为它调用其他系统,并且源代码非常长。

我的build.gradle中的重要依赖项:

代码语言:javascript
复制
def versions = [
        logback: '1.2.3',
        owner: '1.0.10',
        jackson: '2.9.6',

        guava: '25.1-jre',
        guice: '4.2.0',
        grpc: '1.9.1',
        protoc: '3.5.1',

        redis: '2.9.0',
]

依赖关系{

代码语言:javascript
复制
compile group: 'ch.qos.logback', name: 'logback-classic', version: versions.logback
compile group: 'org.aeonbits.owner', name: 'owner', version: versions.owner

compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: versions.jackson
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: versions.jackson
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: versions.jackson

compile group: 'com.google.guava', name: 'guava', version: versions.guava
compile group: 'com.google.inject', name: 'guice', version: versions.guice
compile group: 'io.grpc', name: 'grpc-netty', version: versions.grpc
compile group: 'io.grpc', name: 'grpc-protobuf', version: versions.grpc
compile group: 'io.grpc', name: 'grpc-stub', version: versions.grpc
compile 'org.glassfish:javax.annotation:10.0-b28'


compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.1'
compile group: 'javax.activation', name: 'activation', version: '1.1.1'

compile group: 'redis.clients', name: 'jedis', version: versions.redis

}

正如你在我的protobuf定义中看到的,它并不是自引用的。

有没有可能解决这个问题的方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-28 07:22:40

UnknownFieldSet (通过生成的方法Hash.getUnknownFields()到达)包含getter getDefaultInstanceForType(),它返回UnknownFieldSet的单个实例。这个单例实例在getDefaultInstanceForType()中引用自己,Jackson-databind不能自动处理这个问题(参见下面的edit2 )。

你可能想使用来自com.google.protobuf:protobuf-java-utilJsonFormat,它使用canonical encoding而不是Jackson。

祝好运!

当然,你可以使用Mix-in Annotations来处理这种情况,但是EDIT2> JsonFormat绝对是最佳选择……

票数 4
EN

Stack Overflow用户

发布于 2020-04-29 04:45:33

如果您正在使用 WebFlux并尝试produces application/json,您可以执行以下操作来使其适用于所有的映射,返回protobuf 类型:

代码语言:javascript
复制
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
    configurer.defaultCodecs().jackson2JsonEncoder(
        new Jackson2JsonEncoder(Jackson2ObjectMapperBuilder.json().serializerByType(
                Message.class, new JsonSerializer<Message>() {
                    @Override
                    public void serialize(Message value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                        String str = JsonFormat.printer().omittingInsignificantWhitespace().print(value);
                        gen.writeRawValue(str);
                    }
                }
        ).build())
    );
}
票数 5
EN

Stack Overflow用户

发布于 2020-07-22 00:21:31

要将protobuf对象转换为JSON,您应该使用com.google.protobuf.util.JsonFormat包中的以下类:

代码语言:javascript
复制
JsonFormat.printer().print()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52044715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档