68

I have a very simple JSON with reviews for products, like:

{
  "reviewerID": "A2XVJBSRI3SWDI", 
  "asin": "0000031887", 
  "reviewerName": "abigail", 
  "helpful": [0, 0], 
  "unixReviewTime": 1383523200, 
  "reviewText": "Perfect red tutu for the price. ", 
  "overall": 5.0, 
  "reviewTime": "11 4, 2013", "summary": "Nice tutu"
}
{ 
  "reviewerID": "A2G0LNLN79Q6HR", 
  "asin": "0000031887", 
  "reviewerName": "aj_18 \"Aj_18\"", 
  "helpful": [1, 1], 
  "unixReviewTime": 1337990400, 
  "reviewText": "This was a really cute", 
 "overall": 4.0, 
 "reviewTime": "05 26, 2012", 
 "summary": "Really Cute but rather short."
}

I'd like to read it into my Java app using GSON. I have built a class to hold results for each review:

public class Review {
    private String reviewerID;
    private String asin;
    private String reviewerName;
    private ArrayList<Integer> helpful;
    private String reviewText;
    private Double overall;
    private String summary;
    private Long unixReviewTime;
    private String reviewTime;

    public Review() {
        this.helpful = Lists.newArrayList();
    }
    // some getters and setters...

To read the JSON file, my code is:

Gson gson = new Gson();
JsonReader reader = new JsonReader(new FileReader(filename));
Review data = gson.fromJson(reader, Review.class);
data.toScreen(); // prints to screen some values

With this code, I can only retrieve the first review in the JSON, so my question is: how to iterate through all the reader and get the next reviews? I don't need to store the reviews in a List, just need to access the object once. Any help more than welcome.

user299791
  • 2,021
  • 3
  • 31
  • 57
  • Parse the string you receive into a new JSONArray(). For each object in the array, do gson.fromJson(object, Review.class), then add them all to an empty List list = new LinkedList(); As in, parse them all sequentially. – Schaka Apr 30 '15 at 10:57

3 Answers3

114

You have to fetch the whole data in the list and then do the iteration as it is a file and will become inefficient otherwise.

private static final Type REVIEW_TYPE = new TypeToken<List<Review>>() {
}.getType();
Gson gson = new Gson();
JsonReader reader = new JsonReader(new FileReader(filename));
List<Review> data = gson.fromJson(reader, REVIEW_TYPE); // contains the whole reviews list
data.toScreen(); // prints to screen some values
Archit Maheshwari
  • 1,308
  • 1
  • 9
  • 13
  • 4
    I have this error with your code: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ – user299791 Apr 30 '15 at 11:20
  • 1
    check whether your json file is in correct format or not at [jsonlint](http://jsonlint.com) – Archit Maheshwari Apr 30 '15 at 11:34
  • 1
    @Archit Maheshwari - The input is correctly formatted and is valid. It contains two JSON data structures of type 'object'. It is your example that is not working, at least not with gson 2.8.0. Nonetheless, I believe your example provides an interesting approach how to solve the problem. I suggest to add it to Gson's wishlist. – wh81752 Feb 14 '17 at 10:59
  • 8
    Why using type instead of just `Review[] data = gson.fromJson(reader, Review[].class);`? – Line May 17 '17 at 10:48
  • You do not need to use the TypeToken here. Type token is only required when you are dealing with Generics and you need to add a type to ensure that Gson can parse it. If you want more detail you can go https://github.com/google/gson/blob/master/UserGuide.md#TOC-Gson-With-Gradle – paul_f Jul 19 '19 at 09:41
  • @user299791 - your json input should be in a list i.e. [{review1 json}, {review2 json}], then you should not be getting IllegalStateException – kunal Mar 03 '21 at 04:43
30

just parse as an array:

Review[] reviews = new Gson().fromJson(jsonString, Review[].class);

then if you need you can also create a list in this way:

List<Review> asList = Arrays.asList(reviews);

P.S. your json string should be look like this:

[
    {
        "reviewerID": "A2SUAM1J3GNN3B1",
        "asin": "0000013714",
        "reviewerName": "J. McDonald",
        "helpful": [2, 3],
        "reviewText": "I bought this for my husband who plays the piano.",
        "overall": 5.0,
        "summary": "Heavenly Highway Hymns",
        "unixReviewTime": 1252800000,
        "reviewTime": "09 13, 2009"
    },
    {
        "reviewerID": "A2SUAM1J3GNN3B2",
        "asin": "0000013714",
        "reviewerName": "J. McDonald",
        "helpful": [2, 3],
        "reviewText": "I bought this for my husband who plays the piano.",
        "overall": 5.0,
        "summary": "Heavenly Highway Hymns",
        "unixReviewTime": 1252800000,
        "reviewTime": "09 13, 2009"
    },

    [...]
]
alex
  • 8,904
  • 6
  • 49
  • 75
  • I get an error with your code: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Expected value at line 1 column 1 path $ – user299791 Apr 30 '15 at 11:18
  • sorry my file is 3GB, I tried to load with VIM but cannot load it – user299791 Apr 30 '15 at 12:38
  • just show me the first bytes of the file. I suppose your json string is not valid – alex Apr 30 '15 at 12:42
  • man, if you tell me how to do it, I would love to!!! I am on Mac OSX... do you have a line I can copy in the terminal to show it? – user299791 Apr 30 '15 at 12:44
  • you are programmer, do it in java :) : http://www.mkyong.com/java/how-to-read-file-from-java-bufferedreader-example/ first line is enough – alex Apr 30 '15 at 12:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/76648/discussion-between-simone-gabbriellini-and-dit). – user299791 Apr 30 '15 at 13:32
7

In case you need to parse it from a file, I find the best solution to use a HashMap<String, String> to use it inside your java code for better manipultion.

Try out this code:

public HashMap<String, String> myMethodName() throws FileNotFoundException
{
    String path = "absolute path to your file";
    BufferedReader bufferedReader = new BufferedReader(new FileReader(path));

    Gson gson = new Gson();
    HashMap<String, String> json = gson.fromJson(bufferedReader, HashMap.class);
    return json;
}
qiAlex
  • 4,290
  • 2
  • 19
  • 35