NotThatDroid
NotThatDroid

Reputation: 53

How to parse JSON object with Gson to map of unknown type

I'm starting to use Gson with Retrofit, rather than Jackson, to parse some Json from a Wikipedia API that's structured like this:

{
  "batchcomplete": "",
  "query": {
    "pages": {
      "21721040": {
        "pageid": 21721040,
        "ns": 0,
        "title": "Stack Overflow",
        "extract": "Stack Overflow

Within the "pages" object, I'm trying to map the next block to a Map object of key/value type String and WikiSummary, but the object returns null. Through Jackson, if I remember correctly, you could do direct mapping like this, since I don't know the object values that "pages" has within it.

WikiPages.class

public class WikiPages {

    public Map<String, WikiSummary> summaryMap;

    public WikiPages(Map<String, WikiSummary> summaryMap) {
        this.summaryMap = summaryMap;
    }

    public Map<String, WikiSummary> getSummaryMap() {
        return summaryMap;
    }

    public void setSummaryMap(Map<String, WikiSummary> summaryMap) {
        this.summaryMap = summaryMap;
    }

}

WikiSummary

public class WikiSummary {

    public int pageid;
    public String title;
    public String extract;

    public WikiSummary(int pageid, String title, String extract) {
        this.pageid = pageid;
        this.title = title;
        this.extract = extract;
    }

    public int getPageid() {
        return pageid;
    }

    public void setPageid(int pageid) {
        this.pageid = pageid;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getExtract() {
        return extract;
    }

    public void setExtract(String extract) {
        this.extract = extract;
    }
}

Upvotes: 0

Views: 1299

Answers (2)

Lyubomyr Shaydariv
Lyubomyr Shaydariv

Reputation: 21115

You seem just not to need WikiPages since it must be a map itself (for the simplest Gson configuration; otherwise a more complex deserializer is necessary). Therefore Gson is looking for the summaryMap property that is not present in the given JSON, and that's why it's null. The following mappings

final class WikiResponse {
    @SerializedName("batchcomplete")
    final String batchComplete = null;
    @SerializedName("query")
    final WikiQuery query = null; // this is what you seem to be looking for
}

final class WikiQuery {
    @SerializedName("pages")
    final Map<String, WikiSummary> pages = null;
}

final class WikiSummary {
    @SerializedName("pageid")
    final int pageId = Integer.valueOf(0); // can't be null, but a simple `0` literal will be inlined
    @SerializedName("title")
    final String title = null;
    @SerializedName("extract")
    final String extract = null;
}

can represent the JSON (assuming the DTOs above are incoming and not designed as outgoing [otherwise enhanced]; and Gson can assign real values to final fields). Parsing the given JSON and querying the deserialized POJO with wikiResponse.query.pages.get("21721040").title will result in Stack Overflow.

Upvotes: 2

Tanu Garg
Tanu Garg

Reputation: 3067

JSONObject pagesObject = queryObject.getJSONObject("pages");
Set<String> keys = pagesObject.keySet();
for (String k : keys) {
    JSONObject desiredKeyValues = elements.getJSONObject(k);
}

Upvotes: 0

Related Questions