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.
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
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"
},
[...]
]
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;
}
Related
I am struggling a little bit to get a JSON response from the API server in a readable format.
So here is the page I am currently using for exercises:
https://reqres.in/ Position 4, GET LIST Resource
I am able to retrieve the data from the server in the JSON format which looks like:
{
"page": 1,
"per_page": 6,
"total": 12,
"total_pages": 2,
"data": [
{
"id": 1,
"name": "cerulean",
"year": 2000,
"color": "#98B2D1",
"pantone_value": "15-4020"
},
{
"id": 2,
"name": "fuchsia rose",
"year": 2001,
"color": "#C74375",
"pantone_value": "17-2031"
},
and so on. I am able to retrieve one object in the form of String:
[id:1, name:cerulean, year:2000, color:#98B2D1, pantone_value:15-4020]
I have 6 objects like that in an array, I am looping through the JSON response using:
System.out.println("Json Array count: " + count);
for (int i = 0; i<count; i++){
String books = js.getString("data["+i+"]");
System.out.println(books);
}
Is there an easy way to transcribe this data to the list of maps? I.e
K: id, V: 1 and K: name, V: cerulean etc
I am a freshman if it comes for coding.
Here is my whole class:
String baseURI = RestAssured.baseURI = "https://reqres.in";
RequestSpecification rs = given().header("Content-Type","application/json");
Response response = rs.when().get("/api/unknown");
System.out.println(response.getStatusCode());
response.then().statusCode(200);
Assert.assertEquals(200, response.getStatusCode());
String resource = response.prettyPrint();
JsonPath js = new JsonPath(resource);
int count = js.getInt("data.size()");
System.out.println("Json Array count: " + count);
for (int i = 0; i<count; i++){
String books = js.getString("data["+i+"]");
System.out.println(books);
}
Just use generic get of JsonPath in your case like:
public static void main(String[] args) throws URISyntaxException {
String baseURI = RestAssured.baseURI = "https://reqres.in";
RequestSpecification rs = given().header("Content-Type","application/json");
Response response = rs.when().get("/api/unknown");
List<Map> result = response.jsonPath().get("data");
for(Map map: result){
System.out.println(map);
}
}
Using play framework 2.0 and here goes my java code :
String queryString="SELECT watchDuration, date(startTime) from SEData";
Query query=JPA.em().createNativeQuery(queryString);
List<Object[]> resultHours = (List<Object[]>) query.getResultList();
Gson gson = new Gson();
String json = gson.toJson(resultHours);
renderJSON(json);
After browsing for a while, I did try to use Gson, which resulted me with the following output :
[[5.0,"Feb 5, 2014"],[6.0,"Feb 6, 2014"],[1.0,"Feb 7, 2014"],[2.0,"May 3, 2017"],[3.0,"May 4, 2017"]]
Since I'm fetching this data to plot on a c3.js graph, I need it in the following format :
json:[{"value":5, "date":"Feb 5, 2014"},{"value":6, "date":"Feb 6, 2014"},{"value":1, "date":"Feb 7, 2014"},{"value":2, "date":"May 3, 2017"},{"value":3, "date":"May 4, 2017"}]
OR
json: {
value:[5, 6, 1, 2, 3],
date: ["Feb 5, 2014", "Feb 6, 2014", "Feb 7, 2014", "May 3, 2017", "May 4, 2017"]
}
How can I achieve the above format retrieved MySQL database?
I doubt if my approach towards Gson is wrong, because the output that I got is not even a JSON I believe. Guide me towards the right approach if I'm not moving towards one.
Thanks.
The problem is gson doesn't know what the properties are called, so it makes an array of unnamed values.
While adding a new class will simplify things, a new class for every return type of a query means a lot of rather useless classes, especially if they are only used for marshalling.
Instead, you can map a name to each list of properties like so
HashMap<String, ArrayList<Object> > map = new HashMap<String, ArrayList<Object> >();
ArrayList<Object> values = new ArrayList<Object>();
ArrayList<Object> dates = new ArrayList<Object>();
for(int i=0; i < list.size(); i++){
values.add(resultHours.get(i)[0]);
dates.add(resultHours.get(i)[1]);
}
map.put("value", values);
map.put("date", dates);
This produces the desired output:
{
"date": ["Jan","Feb","Mar","April"],
"value": [1,2,3,4]
}
Rather than returning a list of Object[] create an object which is typed
public class ResultHours {
public int value;
public Date date;
}
and then update the getResultList();
List<ResultHours[]> resultHours = (List<ResultHours[]>) query.getResultList();
I've not tested this but in theory it should work!
[
{
"dataset": "Kushman",
"iIndex": 1964,
"sQuestion": "The grocer has peanuts for 3.75 dollars a pound and walnuts for 2.75 dollars a pound. How many pounds of peanuts and walnuts must we mix to get 40 pounds of mixture to sell for 3.00 dollars per pound. ",
"lEquations": [
"(3.75*peanuts)+(2.75*walnuts)=3.0*40.0",
"peanuts+walnuts=40.0"
],
"lSolutions": [
10.0,
30.0
],
"grammarCheck": 1,
"templateNumber": 4
},
{
"dataset": "Kushman",
"iIndex": 2003,
"sQuestion": "Admission tickets to a football game were 60 cents for adults and 25 cents for children. Receipts for the day showed that 280 persons attended and 140 dollars was collected. How many adults attended? How many children attended?",
"lEquations": [
"(60*.01*noof_adults)+(25*.01*noof_childrens)=140.0",
"noof_adults+noof_childrens=280.0"
],
"lSolutions": [
200.0,
80.0
],
"grammarCheck": 1,
"templateNumber": 2
}
]
This is the Json File named as "Kushman.json". I want to parse it and save the results in different text files for Dataset, Questions and Solution as in the JSON file.
Using JsonObjects and JsonArrays its possible.This is just an example how to read json array and object.Using this you can write values back to files.
JSONObject jObject = null;
try {
String res=FileUtils.readFileToString(new File("test.txt"));
jObject = new JSONObject(res);
JSONArray j1 = jObject.JSONArray ("dataset");
System.out.println(j1);
j2 = j1.getJSONObject("lEquations");
System.out.println(j2);
} catch (Exception e) {
System.out.println("Exception: "+e.getMessage());
}
Use Jackson,
ObjectMapper mapper = new ObjectMapper();
Dataset dataset = mapper.readValue(jsonString, Dataset.class);
Dataset create according to json structure
or
Quick-json Parser,
JsonParserFactory factory=JsonParserFactory.getInstance();
JSONParser parser=factory.newJsonParser();
Map jsonMap=parser.parseJson(jsonString);
I prefer Gson but its up to you.
First create a model which gets mapped with your Json data.
public class MyModel {
private String dataset;
private int iIndex;
private String sQuestion;
private String[] lEuqations;
private float[] lSolutions;
private int grammarCheck;
private int templateNumber;
}
After you can map your data with Gson.
Gson gson = new GsonBuilder().create();
List<MyModel> yourModel = gson.fromJson(jsonData, MyModel[].class)
Thats it.
Do not forget to add gson to your gradle (if using gradle).
// https://mvnrepository.com/artifact/com.google.code.gson/gson
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
I have a JSON record that looks like this:
{"ActionRecord": {
"101": {
"Desc": "string 1",
"Done": 1,
"MaxTimes": 2,
"Point": 30,
"Times": 4
},
"102": {
"Desc": "string 2",
"Done": 1,
"MaxTimes": 3,
"Point": 15,
"Times": 13
},
"103": {
"Desc": "string 3.",
"Done": 1,
"MaxTimes": 5,
"Point": 15,
"Times": 24
}, ... }
I can get Jackson to parse this if i create a hacky intermediate class that contains a field for each number, and then use something like this in the class:
#JsonProperty( value = "101" )
public MyClass hundred_one;
#JsonProperty( value = "102" )
public MyClass hundred_two;
#JsonProperty( value = "103" )
public MyClass hundred_three;
But I have to type out all the expected values, so it would be much easier to be able to use an array list of objects, and insert the numeric id into the POJO with Jackson's mapper.
Is there a way have Jackson automatically map it into a class like this? :
public enum ActionRecord {
Something ( "101" ),
SomethingElse( "102" ),
AnotherSomething ( "103" ),
;
String _id;
EK_DailyTaskInfo_ActionRecord( String id )
{
_id = id;
}
public String getId()
{
return _id;
}
public String Desc; // "some string.",
public boolean Done; // 1,
public int Times; // 4
public int MaxTimes; // 2,
public int Point; // 30,
}
It does not have to be an enum this was just something I was trying before I gave up
Jackson can decode it into a Map<String, Record> for you, e.g.
public class Record {
public String Desc; // "some string.",
public boolean Done; // 1,
public int Times; // 4
public int MaxTimes; // 2,
public int Point; // 30,
}
public class ActionRecords {
public Map<String, Record> ActionRecord
}
well I am using GSON library in shown example, Android has it's own api to handle the JSON where a iterator is very useful, code is also available on github
What i want to propose is that you should read all the keys with respect to it's key's and get the JsonObject from there, you you have a JsonList which is not an array this is what you can do
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result); // result is your json data
JsonObject obj = element.getAsJsonObject();
System.out.println(obj.toString());
JsonObject jsonObject = obj.getAsJsonObject("ActionRecord"); // this will get the JsonObject with the key ActionRecord
System.out.println(jsonObject);
Set<Map.Entry<String, JsonElement>> stringSet = jsonObject.entrySet(); // this will map all the JsonObject with it's keys
for (Map.Entry<String, JsonElement> key :stringSet) {
System.out.println(jsonObject.getAsJsonObject(key.getKey()).toString());
}
Once you have the key with it's corresponding JSONObject, you can create populate your own type for that object.
well this is for Gson, you might want to look for equivalent of this in Jackson
output
{"Desc":"string 1","Done":1,"MaxTimes":2,"Point":30,"Times":4}
{"Desc":"string 2","Done":1,"MaxTimes":3,"Point":15,"Times":13}
{"Desc":"string 3.","Done":1,"MaxTimes":5,"Point":15,"Times":24}
I'm trying to parse the spotify web-service response to get an artists' tracks which is like this:
{
"info": {
"num_results": 2974,
"limit": 100,
"offset": 0,
"query": "foo",
"type": "track",
"page": 1
},
"tracks": [
{
"album": {
"released": "2009",
"href": "spotify:album:1zCNrbPpz5OLSr6mSpPdKm",
"name": "Greatest Hits",
"availability": {
"territories": "AD AR AT AU BE BG BO BR CA CH CL CO CR CY CZ DE DK DO EC EE ES FI FR GB GR GT HK HN HU IE IS IT LI LT LU LV MC MT MX MY NI NL NO NZ PA PE PH PL PT PY RO SE SG SI SK SV TR TW US UY"
}
},
"name": "Everlong",
"popularity": "0.79",
"external-ids": [
{
"type": "isrc",
"id": "USRW29600011"
}
],
"length": 249.986,
"href": "spotify:track:07q6QTQXyPRCf7GbLakRPr",
"artists": [
{
"href": "spotify:artist:7jy3rLJdDQY21OgRLCZ9sD",
"name": "Foo Fighters"
}
],
"track-number": "3"
}]
}
I am using the Gson library to do this. So far I have tried this in my java code:
JsonParser parser = new JsonParser();
JsonObject jObject = parser.parse(jsonString).getAsJsonObject();
JsonArray jArray = jObject.get("tracks") .getAsJsonArray();
Gson gson = new Gson();
List<Track> trackArr = new ArrayList<Track>();
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackColl = gson.fromJson(jArray.toString(), collectiontype);
But I am getting the error : com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
I don't understand why is it expecting begin object if I am doing "getAsJsonArray()" when trying to get the "tracks" object whihc in the json string is an array [].
The list of 'Track' was when I was doing this in a loop to get all the tracks into an array:
for (JsonElement jsonElement : jArray) {
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackCol = gson.fromJson(jsonElement, collectiontype);
trackArr.add((Track) trackCol);
}
What am I doind wrong here ?
I appreciate any guidance.
You don`t have to use extra library to parse a JSON file. Also use this link to read your JSON file in a human readable way.
Use the Native one as the following example:
Imports:
import org.json.JSONArray;
import org.json.JSONObject;
The code of parsing will be:
JSONObject fileJSONObject = new JSONObject(response);
JSONObject infoJSONObject = fileJSONObject.getJSONObject("info");
JSONArray tracksJSONArray = fileJSONObject.getJSONArray("tracks");
//Parsing the info
String trackType = infoJSONObject.getString("type");
String trackLimit = infoJSONObject.getString("limit");
//The rest of attributes
//Parsing the track list
JSONObject object;
for(int i=0;i<tracksJSONArray.length();i++){
object = tracksJSONArray.getJSONObject(i);
String trackName = object.getString("name");
//The rest of attributes
}
I recommend for you to Create a track class that contain all the needed attributes and their setter and getter and at the end of the parsing of each track create a new track.
I hope it helps
You can use my lib for solve this problem. For example you can do it.
private static List<Object> SpotifyTest()
{
InformationHandler informationHandler = null;
Injector injector = Guice.createInjector(new Module());
informationHandler = injector.getInstance(SpotifyService.class);
informationHandler.executeWithValue("la bamba");
return informationHandler.getDataModel();
}
The solution returns a List with a lot of HashMap where each key is a enumeration of key on service, the enumarator is:
public enum SpotifyKey
{
ALBUM_RELEASED,
ALBUM_HREF,
ALBUM_NAME,
ALBUM_AVAILABILITY,
NAME,
POPULARITY,
LENGTH,
HREF,
ARTIST_HREF,
ARTIST_NAME,
TRACK_NUMBER,
ID
}
Also you can view the code on github https://github.com/WeCodeMx/WCMPopularService/tree/develop