How to get List of Objects from deeper level in Json via GSON

Sometimes you get a quite nested Json response but the only thing you need is a list of classes in a certain branch of the Json document (like a response of Yahoo’s YQL query).

Assume just the following json document:

{
"fieldA": {
    "fieldB": {
        "fields": [
            { "foo": "test1", "bar": "test2"},
            { "foo": "test11", "bar": "test22"}
         ]
      }
   }
}

And the only thing you need is the fields array.
A Java8 way to get the fields as a list would be:

List<FooBar> quotes2 = Stream.of(gson.fromJson(json, JsonObject.class)
	.getAsJsonObject("foo")
	.getAsJsonObject("bar")
	.getAsJsonArray("foobar"))
	.flatMap(e -> Stream.of(gson.fromJson(e, FooBar[].class)))
	.collect(Collectors.toList());

But that’s quite some code. Okay if you only need it once, but as soon as you need this several times it clearly violates the DRY principle. Gson (which I am using a lot) doesn’t seem to provide a simple way for doing this. Except creating the whole hierarchy as Java Classes, which might just be overkill.

Solving the problem in a more generic way is the way to go – but it als requires creating generic arrays:

class Gsons{
    public static <T> List<T> asList(String json, String path, Class<T> clazz) {
        Gson gson = new Gson();
        String[] paths = path.split("\\.");
        JsonObject o = gson.fromJson(json, JsonObject.class);
        for (int i = 0; i < paths.length - 1; i++) {
            o = o.getAsJsonObject(paths[i]);
        }
        JsonArray jsonArray = o.getAsJsonArray(paths[paths.length - 1]);
        Class<T[]> clazzArray = (Class<T[]>) ((T[]) Array.newInstance(clazz, 0)).getClass();
        T[] objectArray = gson.fromJson(jsonArray, clazzArray);
        return Arrays.asList(objectArray);
    }
}

The only things to do are creating a class for the entities and calling the method:

List<FooBar> fooBars = Gsons.asList(json, "fieldA.fieldB.fields", FooBar.class);

Android HTTP POST authentication error with Basic Auth

In one of my Android apps, a user should be able to push JSON data to the server. Of course this should only be allowed if the user is authorized by his credentials. For simplicity, I decided to use Basic Auth via HTTPS.

As I usually do not deal with Connectsions directly, I prefer to use the Apache Http classes to make life easier. So I used code like the following:

HttpParams httpParams = new BasicHttpParams();
HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);
HttpProtocolParams.setHttpElementCharset(httpParams, HTTP.UTF_8);
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
client = new DefaultHttpClient(httpParams);
client.getCredentialsProvider().setCredentials(
    new AuthScope("localhost",80),
    new UsernamePasswordCredentials(username, password)
);

This was fine and worked in my local test environment and also in the live stage with GET requests. But when I started to POST data to the server I always got a “401 Unauthorized”. First I thought It’d be malformated JSON or encoding issues – but even with an empty string as payload I simply didn’t get through. Also the “same” POST request from the commandline using CURL worked like a charm! So it was very likely to be an issue with my handling of the Apache HTTP Lib. Stackoverflow also showed various people with the same problem. The proposed solution that came up several times was to manually set up the auth header. Not really the solution that I thought would be the greatest one.

After some more StackOverflow Posts and API crawling I found the very simple solution:

client.getCredentialsProvider().setCredentials(
   new AuthScope(AuthScope.ANY),
   new UsernamePasswordCredentials(username, password)

And yes, it was that easy! Just set the Auth scope correctly.

I’m just very surprised that I only encountered issues with the POST request. The very same configuration worked with a GET without problems. This was actually the point that made me sure that this part of the code was correct.