Azure Functions tip: making sense of GSON JsonSyntaxException
Tags: serverless, azure, java, showdev
Published: 2020-03-13 12:30:56

I was working on [Azure Functions](https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=devto-blog-abhishgu) using [Azure Event Hubs](https://docs.microsoft.com/azure/event-hubs/?WT.mc_id=devto-blog-abhishgu) trigger and this error popped up:

```
Result: Failure
Exception: IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
Stack: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
	at com.google.gson.Gson.fromJson(Gson.java:927)
	at com.google.gson.Gson.fromJson(Gson.java:892)
	at com.google.gson.Gson.fromJson(Gson.java:841)

.... //omitted for brevity
```

### What could possibly go wrong?

![](https://media.giphy.com/media/3o7btPCcdNniyf0ArS/giphy-downsized.gif)

**TL;DR** Please don't forget to use the right cardinality with when using [Event Hubs Trigger with Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-triggers-bindings?WT.mc_id=devto-blog-abhishgu), and if you do, hopefully you stumble across this blog post if you `Google it on Bing!` ;-)

### the (slightly) longer version...

This error was new to me. On further introspection, I realized that the problem was related to the Azure Functions platform not being able to invoke the function method itself (i.e. it had nothing to do with the function logic itself)

> By the way, there are many features to make troubleshooting Azure Functions easier
> - [Built-in Monitoring](https://docs.microsoft.com/azure/azure-functions/functions-monitoring?WT.mc_id=devto-blog-abhishgu) and [Log analysis](https://docs.microsoft.com/azure/azure-functions/functions-monitor-log-analytics?tabs=csharp&WT.mc_id=devto-blog-abhishgu)
> - [Diagnostics](https://docs.microsoft.com/azure/azure-functions/functions-diagnostics?WT.mc_id=devto-blog-abhishgu)
> - Remote debugging [using VS Code](https://code.visualstudio.com/docs/java/)

Azure Functions uses the [`gson` library to serialize/de-serialze payloads](https://docs.microsoft.com/azure/azure-functions/functions-reference-java?WT.mc_id=devto-blog-abhishgu#pojos)

Here is a snippet of the method:

```
@FunctionName("processData")
public void process(
    @EventHubTrigger(name = "event", eventHubName = "", connection = "EventHubConnectionString") 
    Data data, final ExecutionContext context) {
        //implementation
    }
```

In this case, it failed to convert Event Hubs payload to the `Data` POJO which the method was expecting. 


I looked into the [Azure Functions Java API docs](https://docs.microsoft.com/java/api/overview/azure/functions/runtime?view=azure-java-stable&WT.mc_id=devto-blog-abhishgu) to confirm whether I was using the [`@EventHubTrigger`](https://docs.microsoft.com/java/api/com.microsoft.azure.functions.annotation.eventhubtrigger?view=azure-java-stable&WT.mc_id=devto-blog-abhishgu) properly. And I stumbled across the [`cardinality` property](https://docs.microsoft.com/java/api/com.microsoft.azure.functions.annotation.eventhubtrigger.cardinality?view=azure-java-stable&WT.mc_id=devto-blog-abhishgu#com_microsoft_azure_functions_annotation_EventHubTrigger_cardinality__)

Here is the definition:

*Cardinality of the trigger input. Choose 'One' if the input is a single message or 'Many' if the input is an array of messages. 'Many' is the default if unspecified* .. and its default value is `Cardinality.MANY`

The aha moment! Now it wasn't too hard to make sense of the error message `Expected BEGIN_OBJECT but was BEGIN_ARRAY` - because of the `Cardinality`, the platform was attempting to serialize a list/array of `Data` POJOs, but the method was expecting only one. Including the `cardinality` explicitly (`Cardinality.ONE`) was the solution i.e.

```
@EventHubTrigger(
    name = "event", 
    eventHubName = "", 
    connection = "EventHubConnectionString",
    cardinality = Cardinality.ONE) 
```

> Another way is to change the signature to accept `List<Data>` and select the first item in the list e.g. `data.get(0)`

That's all for now. If you found this helpful, show some :heart: and stay tuned for more 🙌 !