Is there an existing Quarkus function to deserialise a CloudEvent from a JSON String?

242 views Asked by At

I am currently working with Quarkus, and I encountered an issue while wanting to deserialise a JSON String message recieved through a WebSocket to a CloudEvent.

Using the Quarkus ObjectMapper doesn't work since the Quarkus CloudEvent stack is using private classes and a builder to instantiate CloudEvents. I can't then use the following :

public CloudEvent<?> createCloudEvent(String message) throws JsonProcessingException {
    return objectMapper.readValue(message, SimpleCloudEvent.class);
}

I tried eluding this issue with this :

public CloudEvent<?> createCloudEvent(String message) throws JsonProcessingException {
    return objectMapper.readValue(message, CloudEventBuilder.create().build(null).getClass());
}

But this time the mapper cannot deserialise the headers that are not part of the CloudEvent specification into the extensions field, as the SimpleCloudEvent constructor doesn't have any explicit field for every possible header.

Nevertheless, using Funqy Knative in another project, I still assume that the Quarkus ObjectMapper can deserialise String or JSON objects to CloudEvents. The following code snippet might explain why I think that :

@Funq
public void receiveCloudEvent(CloudEvent<String> cloudEvent) {
    //do something with the received CE
}

Here, what is sent to my application is an HTTP request, that ultimately is a JSON object. Therefore, either the Quarkus framework or the Funqy Knative one is able to translate it to a valid SimpleCloudEvent, even containing the headers that are not part of the CloudEvent specification in the extensions map.

Does anyone know what class/function the framework is using and if they are usable ?

Or should I really just make a custom deserializer ?

Thanks a lot !

2

There are 2 answers

0
Matej Vašek On BEST ANSWER

Knative Funq should indeed deserialize JSON Values (Object,String,Number,Boolean,Array,Null).

Your example:

@Funq
public void receiveCloudEvent(CloudEvent<String> cloudEvent) {
    //do something with the received CE
}

This function expects JSON String (not Object) as data. Example of valid invocation via cURL:

curl "http://localhost:8080" \    
  -H "Content-Type:application/json" \
  -H "Ce-Id:42" \
  -H "Ce-Source:sample-source" \
  -H "Ce-Type:sample-input" \
  -H "Ce-Specversion:1.0" \
  -d '"json string"'

Note the quotation marks in data.

Example for JSON Object could be:

public class Person {
    public String name;
    public int age;
}

public void receiveCloudEvent(CloudEvent<Person> cloudEvent) {
    //do something with the received CE
}

cURL invocation:

curl "http://localhost:8080" \    
  -H "Content-Type:application/json" \
  -H "Ce-Id:42" \
  -H "Ce-Source:sample-source" \
  -H "Ce-Type:sample-input" \
  -H "Ce-Specversion:1.0" \
  -d '{"name": "John", "age": 42 }'

Lastly there is an escape hatch when you want to deserialise by yourself using byte[]:

public void receiveCloudEvent(CloudEvent<byte[]> cloudEvent) {
    // deserialize data from byte array
}

The Funq serialization/deserialization is private. If you want something more open look at https://github.com/cloudevents/sdk-java.

0
Serkan On

This has nothing to do with Quarkus.

You need to look at Jackson. If you google: Jackson and builder pattern, you will find enough information about this problem.

Or you might also need to look at Jackson mixins, if CloudEvent is coming as a 3rd party lib.