1

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.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.