I'm using the Flickr API. When calling the flickr.test.login
method, the default JSON result is:
{
"user": {
"id": "21207597@N07",
"username": {
"_content": "jamalfanaian"
}
},
"stat": "ok"
}
I'd like to parse this response into a Java object:
public class FlickrAccount {
private String id;
private String username;
// ... getter & setter ...
}
The JSON properties should be mapped like this:
"user" -> "id" ==> FlickrAccount.id
"user" -> "username" -> "_content" ==> FlickrAccount.username
Unfortunately, I'm not able to find a nice, elegant way to do this using Annotations. My approach so far is, to read the JSON String into a Map<String, Object>
and get the values from there.
Map<String, Object> value = new ObjectMapper().readValue(response.getStream(),
new TypeReference<HashMap<String, Object>>() {
});
@SuppressWarnings( "unchecked" )
Map<String, Object> user = (Map<String, Object>) value.get("user");
String id = (String) user.get("id");
@SuppressWarnings( "unchecked" )
String username = (String) ((Map<String, Object>) user.get("username")).get("_content");
FlickrAccount account = new FlickrAccount();
account.setId(id);
account.setUsername(username);
But I think, this is the most non-elegant way, ever. Is there any simple way, either using Annotations or a custom Deserializer?
This would be very obvious for me, but of course it doesn't work:
public class FlickrAccount {
@JsonProperty( "user.id" ) private String id;
@JsonProperty( "user.username._content" ) private String username;
// ... getter and setter ...
}
Since I don't want to implement a custom class (
Username
) just to map the username, I went with a little bit more elegant, but still quite ugly approach:It's still not as elegant as I hoped, but at least I got rid of all the ugly casting. Another advantage of this solution is, that my domain class (
FlickrAccount
) is not polluted with any Jackson annotations.Based on @Michał Ziober's answer, I decided to use the - in my opinion - most straight forward solution. Using a
@JsonDeserialize
annotation with a custom deserializer:But the deserializer does not use any internal classes, just the
JsonNode
as above:You can also use SimpleModule.
You have to make Username a class within FlickrAccount and give it a _content field
You can write custom deserializer for this class. It could look like this:
After that, you have to define a deserializer for your class. You can do this as follows: