GSON Expected BEGIN_ARRAY but was BEGIN_OBJECT

Your issue results really weird for me... it seems that there must be some problem with Jersey's JSON serialization of single element arrays... if you Google "Jersey JSON single element arrays" you'll find the same issue, like here or here. I don't know too much about Jersey, so I can't help you with that...


That said, I can suggest a workaround using manually parsing in Gson, to adapt your parsing to the 2 different responses (object or array). You could do something like this:

//manually parsing until get the "project" element...
JsonParser parser = new JsonParser();
JsonObject rootObejct = parser.parse(yourJsonString).getAsJsonObject();
JsonElement projectElement = rootObejct.get("project");

Gson gson = new Gson();
List<Project> projectList = new ArrayList<>();

//Check if "project" element is an array or an object and parse accordingly...
if (projectElement.isJsonObject()) {
    //The returned list has only 1 element
    Project project = gson.fromJson(projectElement, Project.class);
    projectList.add(project);
}
else if (projectElement.isJsonArray()) {
    //The returned list has >1 elements
    Type projectListType = new TypeToken<List<Project>>() {}.getType();
    projectList = gson.fromJson(projectElement, projectListType);
}

//Now you have a List<Project> projectList with one or many Project elements, 
//depending on the response...

Note that you don't need your class ProjectContainer.

Something like this should work for you, although obviously the best thing would be fix the serialization issue!


Basically, your web service is broken in terms of how it's replying. If there's only one object for project it's returning only an object instead of an array.

MikO's answer solves the problem but another approach is encapsulating that logic in a custom deserializer:

class MyDeserializer implements JsonDeserializer<ProjectContainer> {

    @Override
    public ProjectContainer deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {

        JsonObject jo = je.getAsJsonObject().getAsJsonObject("project");
        if (jo.isJsonArray()) {
             return new Gson().fromJson(je, ProjectContainer.class);
        } else {
             Project p = jdc.deserialize(jo, Project.class);
             List<Project> pList = new ArrayList<Project>(1);
             pList.add(p);
             ProjectContainer pc = new ProjectContainer();
             pc.setProjects(pList);
             return pc;
        }
    }
}

Then you can use:

Gson gson = new GsonBuilder()
                .registerTypeAdapter(ProjectContainer.class, new MyDeserializer())
                .build();
ProjectContainer pContainer = gson.fromJson(myJson, ProjectContainer.class);