Search code examples
deserializationquarkusobjectmappercloudevents

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


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 !


Solution

  • 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.