Using Gson to parse JSON (Generated by Fractal) - java

I'm just wondering if someone can help me..
So, I have an API that I have developed using Fractal to parse the objects to generate some nice JSON to be consumed by an android app i'm making.
The JSON output looks a little something like this:
{
"data": [
{
"id": 1,
"name": "John Smith",
"description": "Information about John Smith",
"games": {
"data": [
{
"name": "Batman Arkham City",
"description": "Information about Game 1"
},
{
"name": "Silent Hill",
"description": "Information about Game 2"
}
]
}
}
]
}
To parse this using Gson, I obviously have to create a Person model which has an ArrayList The thing is.. Note the data key? How do I instruct Gson to parse this? I understand removing that to have the JSON look like this:
{
"data": [
{
"id": 1,
"name": "John Smith",
"description": "Information about John Smith",
"games": [
{
"name": "Batman Arkham City",
"description": "Information about Game 1"
},
{
"name": "Silent Hill",
"description": "Information about Game 2"
}
]
}
]
}
My Person model looks a little something like this:
public class Person
{
public String name;
public ArrayList<Game> games;
Like I said, removing the data key would allow me to parse the data into Java models like so:
peopleArray = jsonObject.getJSONArray( "data" );
Type listType = new TypeToken<ArrayList<Person>>() {}.getType();
ArrayList<Person> result = new Gson().fromJson( peopleArray.toString(), listType );
So basically, is there any way I can tell Gson that the Games array will have a data key? Sorry for the information overload and hopefully that'll make sense?
Ta

Managed to solve this using custom GSON serialisers/deserialisers.
http://www.studytrails.com/java/json/java-google-json-custom-serializer-deserializer.jsp

Related

Retrofit 2.0: How to map objects with different type

This is my sample JSON Response:
{
"success": true,
"details": {
"banners": [
{
"banner_id": "1",
"file_id": "368",
"title": "INANG KALIKASAN'S BAD HAIR DAY",
"description": "Et aeterno partiendo his, vim ponderum abhorreant et. Eum debet recusabo repudiandae in.",
"created": "2018-03-09 07:56:04",
"modified": "2018-04-02 09:59:54",
"deleted": "",
"file_name": "https://globegfs.imgix.net/uploads/2018-04-02/8a90371e9ad33cf06848b354b1fbd795.jpg",
"orig_file_name": "hero-1.jpg"
}
],
"recent_books": [
{
"content_id": "353",
"category_id": "24",
"title": "One Hundred Fourth Symphony, in D-major",
"author": "Franz Josef Haydn",
"description": "The last of the 12 London Symphonies written by Franz Haydn. This ebook contains copies of the 4 movements in .mid format.",
"tags": [
{
"content_id": "353",
"tag_id": "14",
"created": "2018-04-27 15:57:46",
"tag_name": "Ray Collections"
}
]
}
],
"classics": [
{
"content_id": "353",
"category_id": "24",
"title": "One Hundred Fourth Symphony, in D-major",
"author": "Franz Josef Haydn",
"description": "The last of the 12 London Symphonies written by Franz Haydn. This ebook contains copies of the 4 movements in .mid format.",
"tags": [
{
"content_id": "353",
"tag_id": "14",
"created": "2018-04-27 15:57:46",
"tag_name": "Ray Collections"
}
]
}
]
}
}
Only the banners object has a different list of contents. All the succeeding Json Elements will have the same contents but in a list, having its Json Node its actual title. How can I map this into a HashMap?
I figured it will look something like this:
private List<GFSBannerResponse> banners;
private List<HashMap<String, List<GFSContentResponse>>> featuredContent;
but I still don't have an idea on how to implement this. I am using Retrofit 2.0 and Gson.
I ended up implementing it this way:
#SerializedName("details")
#Expose
private JsonElement details;
I just used JsonParser to parse the content to a JsonElement. Stuck with GSON for all of this, although this wasn't the ideal implementation. Will try to implement a custom Deserializer in the future.

Expected BEGIN_OBJECT but was STRING - json without key

I'm generally a beginner in Android and json, and I'm stuck on one part and need some help. I'm trying to use Rotten Tomatoes json. I managed read almost everything, except the part where there isn't key in json. Here is the json:
{
"movies": [{
"id": "771359313",
"title": "Dumb and Dumber To",
"year": 2014,
"mpaa_rating": "PG-13",
"runtime": 109,
"critics_consensus": "",
"release_dates": {
"theater": "2014-11-14"
},
"ratings": {
"critics_rating": "Rotten",
"critics_score": 25,
"audience_rating": "Spilled",
"audience_score": 54
},
"synopsis": "Jim Carrey and Jeff Daniels reprise their signature roles as Lloyd and Harry in the sequel to the smash hit that took the physical comedy and kicked it in the nuts: Dumb and Dumber To. The original film's directors, Peter and Bobby Farrelly, take Lloyd and Harry on a road trip to find a child Harry never knew he had and the responsibility neither should ever, ever be given. The Farrelly brothers produce Dumb and Dumber To alongside Riza Aziz and Joey McFarland of Red Granite Pictures. They are joined by fellow producers Charles B. Wessler and Bradley Thomas. Universal Pictures will distribute the film in the United States, Canada and select international territories.(C) Universal",
"posters": {
"thumbnail": "http://content6.flixster.com/movie/11/17/88/11178864_tmb.jpg",
"profile": "http://content6.flixster.com/movie/11/17/88/11178864_tmb.jpg",
"detailed": "http://content6.flixster.com/movie/11/17/88/11178864_tmb.jpg",
"original": "http://content6.flixster.com/movie/11/17/88/11178864_tmb.jpg"
},
"abridged_cast": [{
"name": "Jim Carrey",
"id": "162659418",
"characters": ["Lloyd Christmas"]
}, {
"name": "Jeff Daniels",
"id": "162654392",
"characters": ["Harry Dunne"]
}, {
"name": "Kathleen Turner",
"id": "162658757",
"characters": ["Fraida Felcher"]
}, {
"name": "Rob Riggle",
"id": "770750133",
"characters": ["Travis/Captain Lippincott"]
}, {
"name": "Jennifer Lawrence",
"id": "770800260",
"characters": ["Young Fraida Felcher"]
}],
"alternate_ids": {
"imdb": "2096672"
},
"links": {
"self": "http://api.rottentomatoes.com/api/public/v1.0/movies/771359313.json",
"alternate": "http://www.rottentomatoes.com/m/dumb_and_dumber_to/",
"cast": "http://api.rottentomatoes.com/api/public/v1.0/movies/771359313/cast.json",
"reviews": "http://api.rottentomatoes.com/api/public/v1.0/movies/771359313/reviews.json",
"similar": "http://api.rottentomatoes.com/api/public/v1.0/movies/771359313/similar.json"
}
}, {
"id": "771355766",
"title": "Big Hero 6",
"year": 2014,
"mpaa_rating": "PG",
"runtime": 93,
"critics_consensus": "",
"release_dates": {
"theater": "2014-11-07"
},
"ratings": {
"critics_rating": "Certified Fresh",
"critics_score": 89,
"audience_rating": "Upright",
"audience_score": 94
},
"synopsis": "With all the heart and humor audiences expect from Walt Disney Animation Studios, \"Big Hero 6\" is an action-packed comedy-adventure about robotics prodigy Hiro Hamada, who learns to harness his genius-thanks to his brilliant brother Tadashi and their like-minded friends: adrenaline junkie Go Go Tamago, neatnik Wasabi, chemistry whiz Honey Lemon and fanboy Fred. When a devastating turn of events catapults them into the midst of a dangerous plot unfolding in the streets of San Fransokyo, Hiro turns to his closest companion-a robot named Baymax-and transforms the group into a band of high-tech heroes determined to solve the mystery. (C) Disney",
"posters": {
"thumbnail": "http://content7.flixster.com/movie/11/17/85/11178581_tmb.jpg",
"profile": "http://content7.flixster.com/movie/11/17/85/11178581_tmb.jpg",
"detailed": "http://content7.flixster.com/movie/11/17/85/11178581_tmb.jpg",
"original": "http://content7.flixster.com/movie/11/17/85/11178581_tmb.jpg"
},
"abridged_cast": [{
"name": "Ryan Potter",
"id": "771360315",
"characters": ["Hiro Hamada"]
}, {
"name": "Scott Adsit",
"id": "406975480",
"characters": ["Baymax"]
}, {
"name": "T.J. Miller",
"id": "770690115",
"characters": ["Fred"]
}, {
"name": "Jamie Chung",
"id": "770694653",
"characters": ["Go Go Tomago"]
}, {
"name": "Damon Wayans Jr.",
"id": "770822247",
"characters": ["Wasabi"]
}],
"alternate_ids": {
"imdb": "2245084"
},
"links": {
"self": "http://api.rottentomatoes.com/api/public/v1.0/movies/771355766.json",
"alternate": "http://www.rottentomatoes.com/m/big_hero_6/",
"cast": "http://api.rottentomatoes.com/api/public/v1.0/movies/771355766/cast.json",
"reviews": "http://api.rottentomatoes.com/api/public/v1.0/movies/771355766/reviews.json",
"similar": "http://api.rottentomatoes.com/api/public/v1.0/movies/771355766/similar.json"
}
}],
"links": {
"self": "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=2&country=us",
"alternate": "http://www.rottentomatoes.com/movie/box-office/"
},
"link_template": "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit={num-results}&country={country-code}"
}
Now, I managed to get name, id, but not the characters. Here are some parts of the code how I got it to work:
public class Movie {
String actor_name;
public Movie(String response, int index) {
Gson gson = new Gson();
MoviesContainer movie = gson.fromJson(response.trim(), MoviesContainer.class);
List < MovieData > movies = movie.movie
AbridgedCastData[] aCast = gson.fromJson(gson.toJson(movies.get(index).abridged_cast), AbridgedCastData[].class);
actor_name = aCast[0].name;
}
}
class MovieData {
Object abridged_cast;
}
class MoviesContainer {
public List < MovieData > movies;
}
class AbridgedCastData {
String name;
String id;
Object characters;
}
I'm using directly index for testing purposes, so actor_name works perfectly.
I tried like this :
CharactersData[] character = gson.fromJson(gson.toJson(aCast[0].characters), CharactersData[].class);
But I'm getting error:
Expected BEGIN_OBJECT but was STRING
I searched everywhere but I can't find how to access characters. How to get for example character Lloyd Christmas? Thanks in advance.
First of all your JSON file is not valid. It should begin with { and end with }. You can check with an online validator such as JSONLint. That's why you get this error.
Secondly if you look at the structure of the file, you see that there is an an array called abridged_cast which contains some objects (which you defined fine in your AbridgedCastData class).
So the final structure could be:
class A {
//contains a list of objects B or an array of objects B
}
class B {
//name
//id
//characters (list of Strings or String array)
}
We are almost done!
When you don't specify a SerializedName annotation, the parser requires that the field name of the attribute you want to serialize must be the same as in the JSON file (otherwise you will end up with a non-initialized value). Since that's not the case you need to add a #SerializedName("abridged_cast") annotation.
Finally you end up with:
public class Test {
public static void main(String[] args) throws FileNotFoundException {
BufferedReader br = new BufferedReader(new FileReader("myJson.json"));
Gson gson = new Gson();
MoviesContainer movie = gson.fromJson(br, MoviesContainer.class);
List<AbridgedCastData> movies = movie.movies;
System.out.println(movies);
}
}
class MoviesContainer {
#SerializedName("abridged_cast")
public List<AbridgedCastData> movies;
}
class AbridgedCastData {
String name;
String id;
List<String> characters;
#Override
public String toString() {
return "AbridgedCastData [name=" + name + ", id=" + id
+ ", characters=" + characters + "]";
}
}
Which outputs:
[AbridgedCastData [name=Jim Carrey, id=162659418, characters=[Lloyd Christmas]], AbridgedCastData [name=Jeff Daniels, id=162654392, characters=[Harry Dunne]], AbridgedCastData [name=Kathleen Turner, id=162658757, characters=[Fraida Felcher]], AbridgedCastData [name=Rob Riggle, id=770750133, characters=[Travis/Captain Lippincott]], AbridgedCastData [name=Jennifer Lawrence, id=770800260, characters=[Young Fraida Felcher]]]
you could change your response and then parse it.
response = "{" + response + "}" ;
// now parse json

Most memory efficient way to re format a JSON array in Java

Say I have a JSON array similar to the following:
[
{
"title": "This is a title",
"year": 2013,
"images": {
"image": "http://........jpg",
},
"ratings": {
"thumbsup": 1053,
"thumbsdown": 256
}
},
{
"title": "This is a title",
"year": 2013,
"images": {
"image": "http://........jpg",
},
"ratings": {
"thumbsup": 1053,
"thumbsdown": 256
}
}
]
And the required output is a JSON array like this:
[
{
"title": "This is a title",
"images": {
"image": "http://........jpg",
},
"ratings": {
"thumbsup": 1053,
}
},
{
"title": "This is a title",
"images": {
"image": "http://........jpg",
},
"ratings": {
"thumbsup": 1053,
}
}
]
Iv'e been researching and it's suggested that the most efficient way would be to parse it using the Jackson streaming API. This is for use on a PaaS with limited memory, so I wish to keep the memory usage to the bare minimum.
Is the best way to parse the JSON with Jackson Streaming API, and construct a new JSON array at the same time or simply remove the elements somehow?
I did something similiar with XML once. You can have the requestor tell you what fields you want to get back, and have it only emit those. In my case I had no control over the 3rd party axis xml view, but once I had the view, when I asked for things from it if it was already there I could give back just the pieces I was interested in. As a bonus, if you are marshalling or unmarshalling real java objects from the JSON after getting the json or XML you don't need to build the part of the object graph you don't care about.

how to read data from json url in java?

I came across the following tutorial:
http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
But this tutorial shows how to convert json to a Java object , when the json file is stored on the user's pc.
What I want to do is, when I go to the following link:
http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[MyApiKey]&q=Toy+Story+3&page_limit=1
it returns me the following json data:
{
"total": 2,
"movies": [{
"id": "770672122",
"title": "Toy Story 3",
"year": 2010,
"mpaa_rating": "G",
"runtime": 103,
"critics_consensus": "Deftly blending comedy, adventure, and honest emotion, Toy Story 3 is a rare second sequel that really works.",
"release_dates": {
"theater": "2010-06-18",
"dvd": "2010-11-02"
},
"ratings": {
"critics_rating": "Certified Fresh",
"critics_score": 99,
"audience_rating": "Upright",
"audience_score": 91
},
"synopsis": "Pixar returns to their first success with Toy Story 3. The movie begins with Andy leaving for college and donating his beloved toys -- including Woody (Tom Hanks) and Buzz (Tim Allen) -- to a daycare. While the crew meets new friends, including Ken (Michael Keaton), they soon grow to hate their new surroundings and plan an escape. The film was directed by Lee Unkrich from a script co-authored by Little Miss Sunshine scribe Michael Arndt. ~ Perry Seibert, Rovi",
"posters": {
"thumbnail": "http://content6.flixster.com/movie/11/13/43/11134356_mob.jpg",
"profile": "http://content6.flixster.com/movie/11/13/43/11134356_pro.jpg",
"detailed": "http://content6.flixster.com/movie/11/13/43/11134356_det.jpg",
"original": "http://content6.flixster.com/movie/11/13/43/11134356_ori.jpg"
},
"abridged_cast": [
{
"name": "Tom Hanks",
"characters": ["Woody"]
},
{
"name": "Tim Allen",
"characters": ["Buzz Lightyear"]
},
{
"name": "Joan Cusack",
"characters": ["Jessie the Cowgirl"]
},
{
"name": "Don Rickles",
"characters": ["Mr. Potato Head"]
},
{
"name": "Wallace Shawn",
"characters": ["Rex"]
}
],
"alternate_ids": {"imdb": "0435761"},
"links": {
"self": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122.json",
"alternate": "http://www.rottentomatoes.com/m/toy_story_3/",
"cast": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/cast.json",
"clips": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/clips.json",
"reviews": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/reviews.json",
"similar": "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json"
}
}],
"links": {
"self": "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Toy+Story+3&page_limit=1&page=1",
"next": "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=Toy+Story+3&page_limit=1&page=2"
},
"link_template": "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q={search-term}&page_limit={results-per-page}&page={page-number}"
}
I want to store this data in a Java Object and then use it. I am a newbie in Java programming.
Thanks.
I would suggest to use something like Gson library, for parsing the Json.
Gson makes it quite elegant and simple.
However, as you are new, I would suggest you to go through the Gson Overview.
Jackson has some built-in methods to read from URLs. You can try the following (using java.net.URL):
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new URL("http://www.mydomain.com/info.json"), User.class);

gson json parser: value without key

I want to parse a json structure like this:
{"response":
{
"arr1":[count,{...}],
"arr2":[count,{...}]
}
}
Everything is ok if count have key "count" (for example). But the key is blank. Is it any way to map this structure and manually retrive only this value or i need to parse all of this json myself without gson ?
UPDATED
Here is a valid json (checked with http://jsonlint.com/)
{
"response": {
"arr1": [
615,
{
"body": "hi",
"title": "Re(2): ..."
},
{
"body": "hello",
"title": "Re(23): ..."
}
],
"arr2": [
132,
{
"body": "hi",
"title": "Re(2): ..."
},
{
"body": "hello",
"title": "Re(23): ..."
}
]
}
}
If you want to parse arbitrary collections you should read Serializing and Deserializing Collection with Objects of Arbitrary Types and look at the example code example code.

Categories

Resources