Parsing a JSON response into a Java object is a super common task in Android development. If you are fortunate enough to have a well-formed JSON response that would make sense being modeled directly as a Java object, then using a JSON parser library can save you lots of time and boiler plate code.
For quite awhile I have used GSON, a JSON parser from Google. Why? To be honest, because that’s what most of my friend developers used, and it always worked well for my use cases. But recently I was challenged to parse a very large JSON object, and I was forced to give GSON a second look to make sure it was the most performant library I could use for a giant response. I found this excellent article on JSON parsing libraries, which showed that a library called Jackson was considerably faster at parsing large JSON files than GSON.
So I set off to implement Jackson in my project! Jackson certainly has a lot of documentation, but it seemed really verbose to me and it felt like it dove straight into juicy details and options, while glossing over the foundations. I didn’t need any of the fancy stuff, and it took awhile to extract the basics from the existing docs, so I’d like to share with you what you’ll need to know to get it up and running in your Android project.
Gradle updates
First you need to pull in the main Jackson lib and a few of its supplemental libs as dependencies in your Gradle file. In your app
level build.gradle
file within dependencies
, add the following:
dependencies { ... compile 'com.fasterxml.jackson.core:jackson-core:2.4.1' compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.1' compile 'com.fasterxml.jackson.core:jackson-databind:2.4.1' }
Depending on your version of gradle / gradle plugin / Android Studio, you may also have to add this packaging option to andrdoid
if you get a build error:
android { ... packagingOptions{ pickFirst 'META-INF/LICENSE' } }
Now you should be ready to use Jackson in your code.
Java Updates
Its been super cold here in Denver the past few days, so I’m going to use the PokeAPI JSON response for Articuno (an ice Pokemon) for our example JSON.** The response is quite long so I won’t be pasting it directly here. Check it out by hitting `http://pokeapi.co/api/v2/pokemon/144/` on your favorite API tool (or just type it in on PokeAPI’s homepage).
Create a new Java class in your project name. I’m naming mine Pokemon
since we want a generic model for all Pokemon, not just Articuno (who is a specific type of Pokemon). For now I’m just creating a single member variable name
in the class:
public class Pokemon { private String name; }
By default, Jackson expects the Java item name to exactly match the JSON item name, which is why I’ve named the Java variable name
and not pokemonName
.
You’ll also need to add some code to get that JSON response into a String. Check out my final sample code if you want help with that. Now in our MainActivity
we need to execute some code to tell Jackson to parse the JSON for us. First we will create an ObjectMapper.
Then we will pass the ObjectMapper
our JSON String and the Java class we are creating an object for:
// Create Jackson ObjectMapper instance ObjectMapper objectMapper = new ObjectMapper(); // Convert json string to object try { articuno = objectMapper.readValue(jsonString, Pokemon.class); } catch (IOException e){ e.printStackTrace(); }
At first, this looks like that is all we’d need to create the Pokemon
object articuno
. However, by default Jackson requires every item from the JSON to have a representation in your Java object. If it doesn’t, Jackson will simply fail to create your Java object. Unfortunately, Jackson does not print out an obvious error message when this happens. Womp womp. Instead it prints out this easy to miss (but still helpful) warning message in the logs:
`com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “forms” (class com.kiodev.jacksonexample.Pokemon), not marked as ignorable (0 known properties: ])`
The log says Jackson can’t recognize forms
which is the first item in our JSON response, which we haven’t defined in our Pokemon
object. But what if I don’t care about forms and don’t want to parse that object out? Thankfully we can ask Jackson to only parse out the items we explicitly define in our Java object with this annotation on the class:
@JsonIgnoreProperties(ignoreUnknown = true) public class Pokemon { private String name; }
For Jackson to parse out your data, you will need to set explicit getters and setters for each object. I’ve chosen a few objects to work with for this example, and created getters and setters for each object:
@JsonIgnoreProperties(ignoreUnknown = true) public class Pokemon { private String name; private String weight; private PokemonSprites sprites; private ArrayList<PokemonFullType> types; public String getName() { return name; } public void setName(String name) { this.name = name; } // etc etc }
Both sprites
and types
are using custom Java types. That is because each of these JSON items contain more information than just a single primitive type. For example, the sprites
JSON object looks like this:
"sprites": { "back_female": null, "back_shiny_female": null, "back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/144.png", "front_female": null, "front_shiny_female": null, "back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/shiny/144.png", "front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/144.png", "front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/144.png" },
I usually like to append List on the end of variables that are lists, like types
, just to be explicit. But types
is the JSON names in the response, so I’m forced to use it, right? Well luckily we can set an annotation on member variables which allows us to use our own names for the Java object! Here is how:
@JsonProperty("types") private ArrayList<PokemonFullType> typesList;
Take a look at my sample code to see the full implementation of these Java classes.
And that’s all you need! You should now be able to parse your JSON response into a Java object using Jackson. More information on Jackson can be found here and here.
The code from this example can be found here on Github.
*Image via http://www.jackson-pollock.org/. Also, I have no idea for whom the Jackson library was named. It may or may not be for Jackson Pollock 😀
**PokeAPI returns information about Pokemon. Pokemon are fictional animals that are part of a series of video games, card games, and anime. In our example, Articuno is the name of one of these Pokemon.