FasterXML / jackson-dataformats-binary

Uber-project for standard Jackson binary format backends: avro, cbor, ion, protobuf, smile
Apache License 2.0
316 stars 136 forks source link

UUID and Double can't be used when generating schema from class #74

Closed Raniz85 closed 7 years ago

Raniz85 commented 7 years ago

This code:

public class UuidWrapper {

    private UUID id;

    public UUID getId() {
        return id;
    }

    public void setId(final UUID id) {
        this.id = id;
    }

    public static void main(String[] args) {
        ProtobufMapper mapper = new ProtobufMapper();

        try {
            System.out.println(mapper.generateSchemaFor(UuidWrapper.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Produces this exception:

java.lang.UnsupportedOperationException: 'String' type not supported as root type by protobuf
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor._throwUnsupported(ProtoBufSchemaVisitor.java:141)
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor.expectStringFormat(ProtoBufSchemaVisitor.java:97)
    at com.fasterxml.jackson.databind.ser.std.StdSerializer.visitStringFormat(StdSerializer.java:181)
    at com.fasterxml.jackson.databind.ser.std.StdScalarSerializer.acceptJsonFormatVisitor(StdScalarSerializer.java:59)
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtobuffSchemaHelper.acceptTypeElement(ProtobuffSchemaHelper.java:49)
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.getDataType(MessageElementVisitor.java:122)
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.buildFieldElement(MessageElementVisitor.java:86)
    at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.optionalProperty(MessageElementVisitor.java:65)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.depositSchemaProperty(BeanPropertyWriter.java:805)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.acceptJsonFormatVisitor(BeanSerializerBase.java:833)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.acceptJsonFormatVisitor(DefaultSerializerProvider.java:580)
    at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:3641)
    at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:3620)
    at com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper.generateSchemaFor(ProtobufMapper.java:95)
    at UuidWrapper.main(UuidWrapper.java:30)

I get the same error if with a Double (but it complains about Number not being a supported root type). Using a String or a double works - but double can't be optional.

If I parse the following schema instead:

message UuidWrapper {
    required string id = 1;
}

Then both serialising and deserialising with UUID works.

Raniz85 commented 7 years ago

This works:

public class UuidWrapper {

    public static final String SCHEMA = "message StreamId {\n"
            + "    required string id = 1;\n"
            + "    required double number = 2;\n"
            + "}";

    private UUID id;

    private Double number;

    public UUID getId() {
        return id;
    }

    public void setId(final UUID id) {
        this.id = id;
    }

    public Double getNumber() {
        return number;
    }

    public void setNumber(final Double number) {
        this.number = number;
    }

    public static void main(String[] args) throws IOException {
        ProtobufMapper mapper = new ProtobufMapper();

        UuidWrapper original = new UuidWrapper();
        original.setId(UUID.randomUUID());
        original.setNumber(42d);

        ProtobufSchema schema = ProtobufSchemaLoader.std.parse(
                "message UuidWrapper {\n"
                + "    required string id = 1;\n"
                + "    required double number = 2;\n"
                + "}"
        );

        byte[] message = mapper.writer(schema).writeValueAsBytes(original);
        UuidWrapper deserialised = mapper.reader(schema).forType(UuidWrapper.class).readValue(message);

        System.out.println(Objects.equals(original.getId(), deserialised.getId()));
        System.out.println(Objects.equals(original.getNumber(), deserialised.getNumber()));
    }
}
true
true
cowtowncoder commented 7 years ago

Dup of #68, fixed for master (2.9.0.pr3).

Raniz85 commented 7 years ago

Sorry that I missed that one. I could swear I searched before opening this issue, but that might have been in the old repo...

cowtowncoder commented 7 years ago

@Raniz85 no prob, I just closed it recently so easy to miss. Plus the repo move.