0

this is my first time making an external api call in Java, so please bear with me as I'm not very experienced. I got the http request working and got a response, but now I need to parse it.

I'm trying to convert a json array to java objects. I understand the gist of it, but all examples I've seen don't apply to my issue.

I need the 'entities' objects from the json string. The details (which are an array, too) can contain any key/value pair, so I was thinking of putting that in a hashmap in each Entity object. I've tried the gson library, but I can't find any gson example that goes deeper than a single dimensional json array.

I realize this is kind of a broad question, and I don't expect anyone to deliver me a working solution, but a few tips or a link to a relevant guide would go a long way. :)

{
   "return": {
      "entities": [
         {
            "id": 2385,
            "details": [
               {
                  "name": "Other Known Name",
                  "value": "John Wick",
                  "match": false
               }
            ],
            "proofs": [],
            "link": "http://domain.gg/users?id=2385"
         },
         {
            "id": 2384,
            "details": [
               {
                  "name": "Discord ID",
                  "value": "159985870458322944",
                  "match": false
               },
               {
                  "name": "SteamID64",
                  "value": "76561197991558078",
                  "match": true
               },
               {
                  "name": "SteamVanity",
                  "value": "test",
                  "match": false
               },
               {
                  "name": "PS4",
                  "value": "John_S",
                  "match": false
               },
               {
                  "name": "XBox",
                  "value": "John S",
                  "match": false
               },
               {
                  "name": "Email",
                  "value": "[email protected]",
                  "match": true
               },
               {
                  "name": "Comment",
                  "value": "Test user",
                  "match": false
               },
               {
                  "name": "Other Known Name",
                  "value": "Jonathan",
                  "match": false
               },
               {
                  "name": "Reddit",
                  "value": "/u/johns",
                  "match": true
               }
            ],
            "proofs": [],
            "link": "http://domain.gg/users?id=2384"
         },
         {
            "id": 1680,
            "details": [
               {
                  "name": "Other Known Name",
                  "value": "Johny",
                  "match": false
               },
               {
                  "name": "SteamID64",
                  "value": "76561198213003675",
                  "match": true
               }
            ],
            "proofs": [],
            "link": "http://domain.gg/users?id=1680"
         },
         {
            "id": 1689,
            "details": [
               {
                  "name": "Other Known Name",
                  "value": "JohnnyPeto",
                  "match": false
               },
               {
                  "name": "SteamID64",
                  "value": "76561198094228192",
                  "match": true
               }
            ],
            "proofs": [],
            "link": "http://domain.gg/users?id=1689"
         }
      ],
      "notice": "Showing 4 out of 4 matches."
   }
}
3
  • "The details (which are an array, too) can contain any key/value pair". Are you sure this is true? I would expect any half-decent API to adhere to a specification. Otherwise how would you know what to expect? If I'm right, I would find the specification and create a Java object to model the response you receive. Commented Mar 30, 2017 at 12:32
  • ... but I can't find any gson example that goes deeper than a single dimensional json array -- So you even didn't try to make even a tiny experiment? Commented Mar 30, 2017 at 12:38
  • Look at this question: stackoverflow.com/questions/15268594/… I think it will help. Commented Mar 30, 2017 at 12:39

4 Answers 4

1

There are many json serialization/deserialization frameworks available. I would recommend having a look at Jackson.

Basically, you have to create Model corresponding to json schema and deserialize json into object. Based on the example in the question, model will look like this:

@JsonIgnoreProperties(ignoreUnknown = true)
class Response {

    @JsonProperty("return")
    private ResponseObject responseObject;

    public ResponseObject getResponseObject() {
        return responseObject;
    }

    public void setResponseObject(ResponseObject responseObject) {
        this.responseObject = responseObject;
    }
}

@JsonIgnoreProperties(ignoreUnknown = true)
class ResponseObject {
    private List<Entity> entities;

    public List<Entity> getEntities() {
        return entities;
    }

    public void setEntities(List<Entity> entities) {
        this.entities = entities;
    }


}   

@JsonIgnoreProperties(ignoreUnknown = true)
class Entity {
    private String id;
    private List<Details> details;

    public String getId() {
        return id;
    }

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

    public List<Details> getDetails() {
        return details;
    }

    public void setDetails(List<Details> details) {
        this.details = details;
    }

}

@JsonIgnoreProperties(ignoreUnknown = true)
class Details {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Once the model is defined, you can use ObjectMapper class to perform serialization/deserialization, e.g.:

ObjectMapper mapper = new ObjectMapper();
Response response = mapper.readValue("{\"return\": {\"entities\": [{\"id\": 2385,\"details\": [{\"name\": \"Other Known Name\",\"value\": \"John Wick\",\"match\": false}],\"proofs\": [],\"link\": \"http://domain.gg/users?id=2385\"},{\"id\": 2384,\"details\": [{\"name\": \"Discord ID\",\"value\": \"159985870458322944\",\"match\": false},{\"name\": \"SteamID64\",\"value\": \"76561197991558078\",\"match\": true},{\"name\": \"SteamVanity\",\"value\": \"test\",\"match\": false},{\"name\": \"PS4\",\"value\": \"John_S\",\"match\": false},{\"name\": \"XBox\",\"value\": \"John S\",\"match\": false},{\"name\": \"Email\",\"value\": \"[email protected]\",\"match\": true},{\"name\": \"Comment\",\"value\": \"Test user\",\"match\": false},{\"name\": \"Other Known Name\",\"value\": \"Jonathan\",\"match\": false},{\"name\": \"Reddit\",\"value\": \"/u/johns\",\"match\": true}],\"proofs\": [],\"link\": \"http://domain.gg/users?id=2384\"},{\"id\": 1680,\"details\": [{\"name\": \"Other Known Name\",\"value\": \"Johny\",\"match\": false},{\"name\": \"SteamID64\",\"value\": \"76561198213003675\",\"match\": true}],\"proofs\": [],\"link\": \"http://domain.gg/users?id=1680\"},{\"id\": 1689,\"details\": [{\"name\": \"Other Known Name\",\"value\": \"JohnnyPeto\",\"match\": false},{\"name\": \"SteamID64\",\"value\": \"76561198094228192\",\"match\": true}],\"proofs\": [],\"link\": \"http://domain.gg/users?id=1689\"}],\"notice\": \"Showing 4 out of 4 matches.\"}}", Response.class);
System.out.println(response.getResponseObject().getEntities().get(0).getId());

Here's the Javadoc.

Sign up to request clarification or add additional context in comments.

Comments

0

If I were you, I'd use Jackson, not GSON. It's specialized on JavaBeans-style mapping. Write classes like this:

public class Detail{
    private String name;
    private String value;
    private boolean match;
    // + getters / setters
}

public class Entity{
    private int id;
    private List<Detail> details;
    private String link;
    private List<String> proofs;
    // you don't have any example data for this, so I'm assuming strings
    // + getters / setters
}

public class Result{
    private List<Entity> entities;
    private String notice;
    // + getters / setters
}

and do the conversion with something like

Result result = new ObjectMapper().readValue(json, Result.class);

Comments

0

As my fellow stackoverflow users have previously posted, for this kind of initilization Jackson API would be better. I have however posted the solution for your question with Gson.

I noticed that you like your details to be stored as a HashMap with id as key. However, it seems like this id is actually related to the entities and not to the details.

Disclaimer, I got lazy and used an online POJO generator because I did not want to create objects for all of the Json elements ;) It still showcases how it should be done:

class Main{

public static void main(String[] args) throws FileNotFoundException {
//this is just to load the json file
    String input = new Scanner(new File("test.txt")).useDelimiter("\\Z").next();

    System.out.println(input);
    Gson gson = new Gson();
    Example arr = gson.fromJson(input, Example.class);

    System.out.println(arr);
}

public class Detail {

    @SerializedName("name")
    @Expose
    public String name;
    @SerializedName("value")
    @Expose
    public String value;
    @SerializedName("match")
    @Expose
    public Boolean match;
    @Override
    public String toString() {
        return "Detail [name=" + name + ", value=" + value + ", match=" + match + "]";
    }

    }

public class Entity {

    @SerializedName("id")
    @Expose
    public Integer id;
    @SerializedName("details")
    @Expose
    public List<Detail> details = null;
    @SerializedName("proofs")
    @Expose
    public List<Object> proofs = null;
    @SerializedName("link")
    @Expose
    public String link;
    @Override
    public String toString() {
        return "Entity [id=" + id + ", details=" + details + ", proofs=" + proofs + ", link=" + link + "]";
    }

    }

public class Example {

    @SerializedName("return")
    @Expose
    public Return _return;

    @Override
    public String toString() {
        return "Example [_return=" + _return + "]";
    }

    }
public class Return {

    @SerializedName("entities")
    @Expose
    public List<Entity> entities = null;
    @SerializedName("notice")
    @Expose
    public String notice;
    @Override
    public String toString() {
        return "Return [entities=" + entities + ", notice=" + notice + "]";
    }

    }
}

Output

Example [_return=Return [entities=[Entity [id=2385, details=[Detail [name=Other Known Name, value=John Wick, match=false]], proofs=[], link=http://domain.gg/users?id=2385], Entity [id=2384, details=[Detail [name=Discord ID, value=159985870458322944, match=false], Detail [name=SteamID64, value=76561197991558078, match=true], Detail [name=SteamVanity, value=test, match=false], Detail [name=PS4, value=John_S, match=false], Detail [name=XBox, value=John S, match=false], Detail [name=Email, [email protected], match=true], Detail [name=Comment, value=Test user, match=false], Detail [name=Other Known Name, value=Jonathan, match=false], Detail [name=Reddit, value=/u/johns, match=true]], proofs=[], link=http://domain.gg/users?id=2384], Entity [id=1680, details=[Detail [name=Other Known Name, value=Johny, match=false], Detail [name=SteamID64, value=76561198213003675, match=true]], proofs=[], link=http://domain.gg/users?id=1680], Entity [id=1689, details=[Detail [name=Other Known Name, value=JohnnyPeto, match=false], Detail [name=SteamID64, value=76561198094228192, match=true]], proofs=[], link=http://domain.gg/users?id=1689]], notice=Showing 4 out of 4 matches.]]

Comments

0

Despite there are answers suggesting you to use Jackson, you can still accomplish easily with Gson with its default configuration just creating proper relations between mappings:

// A generic response, parameterized with <T>, can hold any type except of primitives
final class Response<T> {

    @SerializedName("return")
    final T ret = null;

}

final class EntitiesAndNotice {

    final List<Entity> entities = null;
    final String notice = null;

}

final class Entity {

    // Unlike Object and any its subclasses, `int` being a primitive cannot be nulled
    // Simple 0 won't work either, because the compiler will inline it
    // So it's a sort of cheating javac to return a value that holds 0 already
    final int id = Integer.valueOf(0);
    final List<Detail> details = null;
    // Your JSON document does not provide enough info on the elements type
    // So it depends on how Gson parses JSON tokens
    final List<Object> proofs = null;
    final URL link = null;

}

final class Detail {

    final String name = null;
    final String value = null;
    // The same for primitive booleans, or Boolean.FALSE
    final boolean match = Boolean.valueOf(false);

}

Example use:

private static final String JSON = "{\"return\":{\"entities\":[{\"id\":2385,\"details\":[{\"name\":\"Other Known Name\",\"value\":\"John Wick\",\"match\":false}],\"proofs\":[],\"link\":\"http://domain.gg/users?id=2385\"},{\"id\":2384,\"details\":[{\"name\":\"Discord ID\",\"value\":\"159985870458322944\",\"match\":false},{\"name\":\"SteamID64\",\"value\":\"76561197991558078\",\"match\":true},{\"name\":\"SteamVanity\",\"value\":\"test\",\"match\":false},{\"name\":\"PS4\",\"value\":\"John_S\",\"match\":false},{\"name\":\"XBox\",\"value\":\"John S\",\"match\":false},{\"name\":\"Email\",\"value\":\"[email protected]\",\"match\":true},{\"name\":\"Comment\",\"value\":\"Test user\",\"match\":false},{\"name\":\"Other Known Name\",\"value\":\"Jonathan\",\"match\":false},{\"name\":\"Reddit\",\"value\":\"/u/johns\",\"match\":true}],\"proofs\":[],\"link\":\"http://domain.gg/users?id=2384\"},{\"id\":1680,\"details\":[{\"name\":\"Other Known Name\",\"value\":\"Johny\",\"match\":false},{\"name\":\"SteamID64\",\"value\":\"76561198213003675\",\"match\":true}],\"proofs\":[],\"link\":\"http://domain.gg/users?id=1680\"},{\"id\":1689,\"details\":[{\"name\":\"Other Known Name\",\"value\":\"JohnnyPeto\",\"match\":false},{\"name\":\"SteamID64\",\"value\":\"76561198094228192\",\"match\":true}],\"proofs\":[],\"link\":\"http://domain.gg/users?id=1689\"}],\"notice\":\"Showing 4 out of 4 matches.\"}}";

private static final Gson gson = new Gson();

private static final TypeToken<Response<EntitiesAndNotice>> responseTypeToken = new TypeToken<Response<EntitiesAndNotice>>() {
};

public static void main(final String... args) {
    final Response<EntitiesAndNotice> response = gson.fromJson(JSON, responseTypeToken.getType());
    final String value = response.ret.entities.get(1).details.get(3).value;
    System.out.println(value);
}

Output:

John_S

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.