protobuf LocalDateTime UnsupportedOperationException
Hello, I'm having trouble serializing LocalDateTime with Protobuf.
Here is what I'm trying to do:
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Data;
import java.time.LocalDateTime;
public class Main {
@Data
static class Foo {
LocalDateTime bar;
}
public static void main(String[] args) throws JsonMappingException {
var mapper = ProtobufMapper.builder()
.addModule(new JavaTimeModule())
.build();
mapper.generateSchemaFor(Foo.class);
}
}
but I get the following exception:
Exception in thread "main" java.lang.UnsupportedOperationException: 'Map' type not supported as type by protobuf module
at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor._throwUnsupported(ProtoBufSchemaVisitor.java:208)
at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor.expectArrayFormat(ProtoBufSchemaVisitor.java:109)
at com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase._acceptTimestampVisitor(JSR310FormattedSerializerBase.java:188)
at com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.acceptJsonFormatVisitor(JSR310FormattedSerializerBase.java:175)
at com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer.acceptJsonFormatVisitor(LocalDateTimeSerializer.java:37)
at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.acceptTypeElement(MessageElementVisitor.java:137)
at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.getDataType(MessageElementVisitor.java:121)
at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.buildFieldElement(MessageElementVisitor.java:86)
at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.optionalProperty(MessageElementVisitor.java:59)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.depositSchemaProperty(BeanPropertyWriter.java:843)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.acceptJsonFormatVisitor(BeanSerializerBase.java:912)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.acceptJsonFormatVisitor(DefaultSerializerProvider.java:588)
at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:4744)
at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:4723)
at com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper.generateSchemaFor(ProtobufMapper.java:144)
at org.example.Main.main(Main.java:17)
Process finished with exit code 1
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>debug</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jackson.version>2.16.1</jackson.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-protobuf</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</project>
Sounds like serializer for LocalDateTime is not producing expected schema structure for given settings.
Quick note: the issue is due to Schema generation for Array types not working (NOT "Map" like exception claims -- I'll do PR for that minor flaw). This because by default LocalDateTime is serialize as Array of 3 integers.
Until fix for schema generation to support arrays is added, the best way to work around this is to serialize LocalDateTime as String, not array: this can be done f.ex by disabling
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
setting on ProtobufMapper.
So: for anyone looking at this issue -- proper fix is to add Protobuf schema generation for Array of JsonFormatTypes.INTEGER as indicated by JSR310FormattedSerializerBase._acceptTimestampVisitor() of Date/Time format module.
But test should work by generating schema for, say, int[].
Ahhhhh. Not quite even that -- using a wrapper, like:
class LocalDateTimeWrapper {
public LocalDateTime value;
}
would make things work. So it's only for root value that there is an issue.
Ok, now I remember: at root level, Protobuf cannot support Array values -- so as long as type like LocalDateTime is serialized as array, it cannot be serialized as the root value: it must be a property of a root-level object / record. This also applies if attempting to serialize as a String, fwtw, fundamental restriction.