1

I have a problem. I am doing a webcall where I print a json on my screen like that looks like this:

{"Agents":[{"Id":"1","Owner":"Andre"},{"Id":"7","Owner":"Andre2"},{"Id":"8","Owner":"Andre"},{"Id":"9","Owner":"Alexander"},{"Id":"10","Owner":"Alexander"},{"Id":"12","Owner":"Andre"}]}

Then I used the following code to get the json from the web and parse it into an array object:

EfyWebAPI webAPI = new EfyWebAPI();
String jsonResponse = webAPI.executeQuery("www.mysite.org/test.php", "SELECT Id, Owner FROM Agents");

Gson gson = new Gson();
Agent[] agents = gson.fromJson(jsonResponse, Agent[].class);

System.out.println(agents[0].getId());

The class looks like this:

public class Agent {

    private int id;
    private String owner;

    public Agent(int id, String owner) {
        this.id = id;
        this.owner = owner;
    }

    public int getId() {
        return this.id;
    }

}

But when I run the code, I get the following error:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $ at com.google.gson.Gson.fromJson(Gson.java:822) at com.google.gson.Gson.fromJson(Gson.java:775) at com.google.gson.Gson.fromJson(Gson.java:724) at com.google.gson.Gson.fromJson(Gson.java:696) at com.company.Main.main(Main.java:18) Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $ at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350) at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:70) at com.google.gson.Gson.fromJson(Gson.java:810) ... 4 more

Why is this happening and how can I fix this?

A. Vreeswijk
  • 1,359
  • 4
  • 23
  • Does this answer your question? ["Expected BEGIN\_OBJECT but was STRING at line 1 column 1"](https://stackoverflow.com/questions/28418662/expected-begin-object-but-was-string-at-line-1-column-1) – fluffy Jan 26 '21 at 22:06
  • Additionally, 1) make sure your server response is a true JSON array; 2) the `Agent` field names won't map the JSON fields: use `@SerializedName` to map `id` to `Id`, etc. – fluffy Jan 26 '21 at 22:08
  • You have a capitalization problem (the class has lower case members, the JSON has upper case). I don't see the `com.google.gson.JsonSyntaxException`, so I suspect the code isn't getting the same string as you posted in your question. – geocodezip Jan 26 '21 at 22:12
  • This error, _`Expected ... but was STRING`_, usually occurs when the response is not a JSON document, but a non-JSON error message (plain text, HTML, whatever) from the server. I strongly recommend the OP to double-check the actual response and check whether it is a JSON at all (printing the response to stdout would be much easier than posting a question here). For example, this is code that also yields the same error: `gson.fromJson("Error!", Agent[].class)`. – fluffy Jan 26 '21 at 22:20
  • 1
    Still no luck parsing the JSON with multiple objects!? Any suggestions? – A. Vreeswijk Jan 27 '21 at 11:13

2 Answers2

0

The error is saying

Expected BEGIN_ARRAY...

because of the second argument (Agent[].class), it is expecting a valid json array string of Agent-s. Your json string is an object with a key Agents and the value is an array of Agents.

A possible solution could be for example creating a class named Agents which represents the json object.

public class Agents {
    private Agent[] Agents; // note the capital 'A' matches the key name in the json string

    public Agent[] getAgents() {
        return Agents;
    }

    public void setAgents(Agent[] agents) {
        this.Agents = agents;
    }
}

And adjust the Agent class as follows:

public class Agent {
    @SerializedName("Id") // note the annotated field is needed since in the json string id is Id
    private int id;

    @SerializedName("Owner") // same as id field, annotation needed, or rename owner to Owner
    private String owner;

    public Agent(int id, String owner) {
        this.id = id;
        this.owner = owner;
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    @Override
    public String toString() {
        return "Agent{" +
                "id=" + id +
                ", owner='" + owner + '\'' +
                '}';
    }
}

And here's a working demo:

public class GsonDemo {
    public static void main(String[] args) {
        String json = "{\"Agents\":[{\"Id\":\"1\",\"Owner\":\"Andre\"},{\"Id\":\"7\",\"Owner\":\"Andre2\"},{\"Id\":\"8\",\"Owner\":\"Andre\"},{\"Id\":\"9\",\"Owner\":\"Alexander\"},{\"Id\":\"10\",\"Owner\":\"Alexander\"},{\"Id\":\"12\",\"Owner\":\"Andre\"}]}";
        Gson gson = new Gson();
        Agents a = gson.fromJson(json, Agents.class);
        System.out.println(a.getAgents()[1]);
        System.out.println(a.getAgents().length);
        // Output:
        // Agent{id=7, owner='Andre2'}
        // 6
    }
}
lainatnavi
  • 953
  • 1
  • 6
  • 16
-1

It works kind of... Instead of getting id=1, it gets id=0. I think it gets the id of the object count from the json. How does this work and why can't I parse multiple objects at once and return it into an array list or something?

JSON (or at least GSON) always expects a string as key (as far as I know). What comes behind the String does not matter, as long as it conforms to the JSON standard.

What you mention would be possible, if you declared something like

{"persons" : [ + rest of your content + ]}, however I'm unsure whether you could automatically parse that into a List<Agent>.

delvh
  • 24
  • 2
  • I updated my JSON again in my question with the root, like you had, but this doesn't work either!? Again the `Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $` Error? – A. Vreeswijk Jan 27 '21 at 00:56