JSON arrays with one element wrongly rendered in ClientSearch response

Hi guys,

I am working on creating an application that will integrate with QuickFile.

This application is a batch app that requires to determine exactly one client to perform actions on. To do so I send a ClientSearch message to the JSON endpoint. I get back a response message (BTW it took me some headache to get the asymmetric “payload” vs. “Client_Search” rendering handled correctly).

However, the response message is inconsistently rendered depending on the number of client entries were found.

If the system found several clients, I get back something like this (abbreviated, and sensitive info obfuscated):

{
	"Client_Search": {
		"Header": {
			"MessageType": "Response",
			"SubmissionNumber": "..."
		},
		"Body": {
			"RecordsetCount": "3",
			"ReturnCount": "3",
			"Record": [
				{
					"ClientID": "****",
					"ClientCreatedDate": "25/05/2017",
					"CompanyName": "*****",
                    ...
				},
				{
					"ClientID": "****",
					"ClientCreatedDate": "25/05/2017",
					"CompanyName": "*****",
                    ...
				},
				{
					"ClientID": "****",
					"ClientCreatedDate": "25/05/2017",
					"CompanyName": "*****",
                    ...
				}
			]
		}
	}
}

If I change the search parameters to get only one result, I get this:

{
	"Client_Search": {
		"Header": {
			"MessageType": "Response",
			"SubmissionNumber": "..."
		},
		"Body": {
			"RecordsetCount": "1",
			"ReturnCount": "1",
			"Record": {
					"ClientID": "****",
					"ClientCreatedDate": "25/05/2017",
					"CompanyName": "*****",
                    ...
			}
		}
	}
}

However, according to json.org the response should be formatted like this for a 1-value array:

{
	"Client_Search": {
		"Header": {
			"MessageType": "Response",
			"SubmissionNumber": "..."
		},
		"Body": {
			"RecordsetCount": "3",
			"ReturnCount": "3",
			"Record": [
				{
					"ClientID": "****",
					"ClientCreatedDate": "25/05/2017",
					"CompanyName": "*****",
                    ...
				}
 			]
		}
	}
}

and for a 0-value 1-value array:

{
	"Client_Search": {
		"Header": {
			"MessageType": "Response",
			"SubmissionNumber": "..."
		},
		"Body": {
			"RecordsetCount": "3",
			"ReturnCount": "3",
			"Record": [
 			]
		}
	}
}

I am using Java 1.8 with Apache Commons Http Client, and GSON (Google’s Java Json library). GSON appears to be very picky, and very rightfully so since www.json.org defines arrays as follows:

array
    []
    [ elements ]
elements
    value 
    value , elements

In other words, an array always includes brackets!

Consequently, I get the following stacktrace exception:

 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170

Thanks,
Michel

I don’t know about Gson, but Jackson has a simple switch that tells it to accept a plain object when expecting an array, and treat it as an array of length 1

There may be something similar in Gson.

The behaviour you’re seeing is sadly common in libraries that aren’t really JSON aware but are just converting another format into JSON - in the QuickFile case it looks to me like their JSON api is really a thin layer on top of the existing XML one, and without access to the schema the JSON converter can’t know when it sees one element whether that is a single thing or a one-element array semantically.

Hi Ian,

The Java POJO uses Arrays to collect the Records - which is why I get hit by the exception I guess.

I did a Google search for this exception, but got only hits for the converse situation, i.e. GSON expecting an object but hitting an array instead…

Are you tied to Gson for other reasons or could you try switching to Jackson instead? It can do the same job of mapping JSON to POJOs.

If your POJO has a List<Whatever> property and you configure your ObjectMapper with enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) then it should Just Work.

(I use QuickFile to do the books for my wife’s shop, but my own day job is writing web and command line applications in Java and Groovy).

I am not irrevocably tied to GSON, however I like its small footprint and ease of use - and the future outlook of perhaps porting to mobile phones where GSON is apparently the thing to use on Android phones…

I will have a look at Jackson though.

Hi @Michel,

I’m afraid there’s not likely to be much we can do here. The JSON API is really just a proxy that converts the JSON to XML and back. I will however ask if we can look at the library (Newtonsoft I believe) to see if there’s anyway we can override this behaviour without breaking any existing implementations.

EDIT:

Well perhaps there’s something we can do.

Hi @Glenn,

That would be really great as that would spare me writing custom type adapters for GSON deserialisation (see https://stackoverflow.com/questions/7668507/gson-handle-object-or-array)

The current behaviour, while lexicographically correct by EBNF, is unfortunately incorrect by JSON intention which indicates arrays to be always rendered with its brackets. (I know JavaScript isn’t type safe, but JSON data structure specification should have been!)

It really does need to be changed. If you can hold out until after the bank holiday, we’ll try to get this updated.

1 Like

Hi @Glenn,

That would be great!

1 Like

On version 1.2 you should now be getting an array for single record responses.

1 Like