I'm trying to dynamically convert a JSON string to a DynamicMessage from the protobuf library.
Currently, I have the following piece of code:
val topic = "sample-topic"
// I'm using confluent schema registry to store/retrieve schemas.
val descriptor: Descriptors.Descriptor = getDescriptorFromRegistry(topic)
// Create a [DynamicMessage] builder and pass the corresponding descriptor.
val builder: DynamicMessage.Builder = DynamicMessage.newBuilder(descriptor)
// Merge json with the descriptor.
JsonFormat.parser().merge(json, builder) // exception occurs here
val message: DynamicMessage = builder.build()
val bytes: ByteArray = message.toByteArray()
And here is the JSON string:
{
"id": 1001,
"firstName": "Bob",
"lastName": "Test",
"email": "[email protected]",
"dateCreated": 1696273647694046
}
And the protobuf schema:
syntax = "proto3";
package io.smyrgeorge.test.proto.domain;
import "google/protobuf/timestamp.proto";`
message Customer {
int32 id = 1;
string firstName = 2;
string lastName = 3;
string email = 4;
google.protobuf.Timestamp dateCreated = 5;
}
So, the problem seems to be Timestamp, I'm getting the following exception:
Exception in thread "main" com.google.protobuf.InvalidProtocolBufferException: Failed to parse timestamp: 1696273647694046 at com.google.protobuf.util.JsonFormat$ParserImpl.mergeTimestamp(JsonFormat.java:1564) at com.google.protobuf.util.JsonFormat$ParserImpl.access$2200(JsonFormat.java:1299) at com.google.protobuf.util.JsonFormat$ParserImpl$3.merge(JsonFormat.java:1394) at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1455) at com.google.protobuf.util.JsonFormat$ParserImpl.parseFieldValue(JsonFormat.java:2018) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1669) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1500) at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1458) at com.google.protobuf.util.JsonFormat$ParserImpl.parseFieldValue(JsonFormat.java:2018) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeOneofField(JsonFormat.java:1708) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1667) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1500) at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1458) at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1340) at com.google.protobuf.util.JsonFormat$Parser.merge(JsonFormat.java:472) at io.smyrgeorge.connect.converter.ProtobufConverter.fromConnectData(ProtobufConverter.kt:93) at io.smyrgeorge.connect.MainKt.main(Main.kt:54) at io.smyrgeorge.connect.MainKt.main(Main.kt) Caused by: java.text.ParseException: Failed to parse timestamp: invalid timestamp "1696273647694046" at com.google.protobuf.util.Timestamps.parse(Timestamps.java:241) at com.google.protobuf.util.JsonFormat$ParserImpl.mergeTimestamp(JsonFormat.java:1561) ... 17 more
The dateCreated field is unix timestamp (microseconds) 1696273647694046.
It seems that the default parser, from the protobuf library, only supports ISO date strings
From the original code (com.google.protobuf.util.Timestamps:238):
/**
* Parse from RFC 3339 date string to Timestamp. This method accepts all outputs of {@link
* #toString(Timestamp)} and it also accepts any fractional digits (or none) and any offset as
* long as they fit into nano-seconds precision.
*
* <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
*
* @return a Timestamp parsed from the string
* @throws ParseException if parsing fails
*/
public static Timestamp parse(String value) throws ParseException {...}
I was trying to convert a json string to protobuf's DynamicMessage type using the JsonFromat class. I was expecting that unix timestamps should be supported.
So is there a way to pass a custom parser for the Timestamp type?
Another option could be to preprocess the json string and convert the dates, but I would like to avoid it.