JSON Parsing using minimal-json and Gson - java

I have a java program which retrieves data for a particular TV show and returns a JSON response with the details.
My problem is with parsing the JSON response to get one particular key-value pair, namely the "first_aired_iso" string, which gives the air date for that episode.
Here is the URL which calls the API
String api_url = "http://api.trakt.tv/show/season.json/<api-key>/the-walking-dead/1";
And here is the corresponding JSON response
! [
{
"season":1,
"episode":1,
"number":1,
"tvdb_id":2493011,
"title":"Days Gone Bye",
"overview":"Rick searches for his family after emerging from a coma into a world terrorized by the walking dead. Morgan and Duane, whom he meets along the way, help teach Rick the new rules for survival.",
"first_aired":1288584000,
"first_aired_iso":"2010-10-31T21:00:00-05:00",
"first_aired_utc":1288598400,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/1",
"screen":"http://slurm.trakt.us/images/episodes/124-1-1.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-1.22.jpg"
},
"ratings":{
"percentage":89,
"votes":763,
"loved":733,
"hated":30
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":false,
"rating_advanced":0
},
{
"season":1,
"episode":2,
"number":2,
"tvdb_id":2493181,
"title":"Guts",
"overview":"Rick unknowingly causes a group of survivors to be trapped by walkers. The group dynamic devolves from accusations to violence, as Rick must confront an enemy far more dangerous than the undead.",
"first_aired":1289192400,
"first_aired_iso":"2010-11-07T21:00:00-06:00",
"first_aired_utc":1289210400,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/2",
"screen":"http://slurm.trakt.us/images/episodes/124-1-2.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-2.22.jpg"
},
"ratings":{
"percentage":87,
"votes":533,
"loved":507,
"hated":26
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":false,
"rating_advanced":0
},
{
"season":1,
"episode":3,
"number":3,
"tvdb_id":2656081,
"title":"Tell It to the Frogs",
"overview":"After returning to the camp with the department store survivors and an emotional reunion with his wife and son, Rick decides to go against Shane's advice and go back to Atlanta for Merle Dixon and his dropped bag of guns accompanied by Merle's younger brother, Darryl Dixon, as well as Glenn and T-Dog.",
"first_aired":1289797200,
"first_aired_iso":"2010-11-14T21:00:00-06:00",
"first_aired_utc":1289815200,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/3",
"screen":"http://slurm.trakt.us/images/episodes/124-1-3.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-3.22.jpg"
},
"ratings":{
"percentage":85,
"votes":484,
"loved":458,
"hated":26
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":false,
"rating_advanced":0
},
{
"season":1,
"episode":4,
"number":4,
"tvdb_id":2656091,
"title":"Vatos",
"overview":"While still in search of Merle, the group tries to retrieve the bag of guns but are attacked by several living men who are also after the weapons. The group manages to grab the injured attacker; however, several of the attackers escape and take Glenn hostage. Back at camp a large group of walkers venture up the hill and take the survivors by surprise.",
"first_aired":1290402000,
"first_aired_iso":"2010-11-21T21:00:00-06:00",
"first_aired_utc":1290420000,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/4",
"screen":"http://slurm.trakt.us/images/episodes/124-1-4.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-4.22.jpg"
},
"ratings":{
"percentage":88,
"votes":490,
"loved":467,
"hated":23
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":false,
"rating_advanced":0
},
{
"season":1,
"episode":5,
"number":5,
"tvdb_id":2656101,
"title":"Wildfire",
"overview":"Rick leads the group to the CDC after the attack on the camp. Jim must make a terrible life and death decision.",
"first_aired":1291006800,
"first_aired_iso":"2010-11-28T21:00:00-06:00",
"first_aired_utc":1291024800,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/5",
"screen":"http://slurm.trakt.us/images/episodes/124-1-5.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-5.22.jpg"
},
"ratings":{
"percentage":87,
"votes":460,
"loved":443,
"hated":17
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":"love",
"rating_advanced":10
},
{
"season":1,
"episode":6,
"number":6,
"tvdb_id":2656111,
"title":"TS-19",
"overview":"Rick and the group are allowed into the CDC by a strange doctor, but all is not what it seems in their newfound haven. ",
"first_aired":1291611600,
"first_aired_iso":"2010-12-05T21:00:00-06:00",
"first_aired_utc":1291629600,
"url":"http://trakt.tv/show/the-walking-dead/season/1/episode/6",
"screen":"http://slurm.trakt.us/images/episodes/124-1-6.22.jpg",
"images":{
"screen":"http://slurm.trakt.us/images/episodes/124-1-6.22.jpg"
},
"ratings":{
"percentage":87,
"votes":465,
"loved":440,
"hated":25
},
"watched":true,
"in_collection":true,
"in_watchlist":false,
"rating":"love",
"rating_advanced":10
}
]
Well, you get the idea...
I just need to extract the key value for "first_aired_iso" for each episode.
Here is my code to do that
String s = response.toString();
Gson gson = new Gson();
String jsonstr = gson.toJson(s);
System.out.println(jsonstr);
JsonArray json = JsonArray.readFrom(jsonstr);
for (int i = 0; i < 15; i++) {
System.out.println(json.get(i).asString());
}
Problem is, there is absolutely no response after printing the raw JSON output.
I can't get it to enter the loop at all.
For reference, please check http://eclipsesource.com/blogs/2013/04/18/minimal-json-parser-for-java/

My solution:
public static void main(String[] args) {
String json = "[ { \"season\":1, \"episode\":1, \"number\":1, \"tvdb_id\":2493011, \"title\":\"Days Gone Bye\", \"overview\":\"Rick searches for his family after emerging from a coma into a world terrorized by the walking dead. Morgan and Duane, whom he meets along the way, help teach Rick the new rules for survival.\", \"first_aired\":1288584000, \"first_aired_iso\":\"2010-10-31T21:00:00-05:00\", \"first_aired_utc\":1288598400, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/1\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-1.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-1.22.jpg\" }, \"ratings\":{ \"percentage\":89, \"votes\":763, \"loved\":733, \"hated\":30 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":false, \"rating_advanced\":0 }, { \"season\":1, \"episode\":2, \"number\":2, \"tvdb_id\":2493181, \"title\":\"Guts\", \"overview\":\"Rick unknowingly causes a group of survivors to be trapped by walkers. The group dynamic devolves from accusations to violence, as Rick must confront an enemy far more dangerous than the undead.\", \"first_aired\":1289192400, \"first_aired_iso\":\"2010-11-07T21:00:00-06:00\", \"first_aired_utc\":1289210400, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/2\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-2.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-2.22.jpg\" }, \"ratings\":{ \"percentage\":87, \"votes\":533, \"loved\":507, \"hated\":26 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":false, \"rating_advanced\":0 }, { \"season\":1, \"episode\":3, \"number\":3, \"tvdb_id\":2656081, \"title\":\"Tell It to the Frogs\", \"overview\":\"After returning to the camp with the department store survivors and an emotional reunion with his wife and son, Rick decides to go against Shane's advice and go back to Atlanta for Merle Dixon and his dropped bag of guns accompanied by Merle's younger brother, Darryl Dixon, as well as Glenn and T-Dog.\", \"first_aired\":1289797200, \"first_aired_iso\":\"2010-11-14T21:00:00-06:00\", \"first_aired_utc\":1289815200, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/3\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-3.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-3.22.jpg\" }, \"ratings\":{ \"percentage\":85, \"votes\":484, \"loved\":458, \"hated\":26 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":false, \"rating_advanced\":0 }, { \"season\":1, \"episode\":4, \"number\":4, \"tvdb_id\":2656091, \"title\":\"Vatos\", \"overview\":\"While still in search of Merle, the group tries to retrieve the bag of guns but are attacked by several living men who are also after the weapons. The group manages to grab the injured attacker; however, several of the attackers escape and take Glenn hostage. Back at camp a large group of walkers venture up the hill and take the survivors by surprise.\", \"first_aired\":1290402000, \"first_aired_iso\":\"2010-11-21T21:00:00-06:00\", \"first_aired_utc\":1290420000, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/4\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-4.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-4.22.jpg\" }, \"ratings\":{ \"percentage\":88, \"votes\":490, \"loved\":467, \"hated\":23 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":false, \"rating_advanced\":0 }, { \"season\":1, \"episode\":5, \"number\":5, \"tvdb_id\":2656101, \"title\":\"Wildfire\", \"overview\":\"Rick leads the group to the CDC after the attack on the camp. Jim must make a terrible life and death decision.\", \"first_aired\":1291006800, \"first_aired_iso\":\"2010-11-28T21:00:00-06:00\", \"first_aired_utc\":1291024800, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/5\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-5.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-5.22.jpg\" }, \"ratings\":{ \"percentage\":87, \"votes\":460, \"loved\":443, \"hated\":17 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":\"love\", \"rating_advanced\":10 }, { \"season\":1, \"episode\":6, \"number\":6, \"tvdb_id\":2656111, \"title\":\"TS-19\", \"overview\":\"Rick and the group are allowed into the CDC by a strange doctor, but all is not what it seems in their newfound haven. \", \"first_aired\":1291611600, \"first_aired_iso\":\"2010-12-05T21:00:00-06:00\", \"first_aired_utc\":1291629600, \"url\":\"http://trakt.tv/show/the-walking-dead/season/1/episode/6\", \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-6.22.jpg\", \"images\":{ \"screen\":\"http://slurm.trakt.us/images/episodes/124-1-6.22.jpg\" }, \"ratings\":{ \"percentage\":87, \"votes\":465, \"loved\":440, \"hated\":25 }, \"watched\":true, \"in_collection\":true, \"in_watchlist\":false, \"rating\":\"love\", \"rating_advanced\":10 } ]";
ArrayList<Map> al = new Gson().fromJson(json, ArrayList.class);
for(Map m : al){
System.out.printf("Ep. %.0f aired on %s\n", m.get("episode"), m.get("first_aired_iso"));
}
}
This is the execution:
1 aired on 2010-10-31T21:00:00-05:00
2 aired on 2010-11-07T21:00:00-06:00
3 aired on 2010-11-14T21:00:00-06:00
4 aired on 2010-11-21T21:00:00-06:00
5 aired on 2010-11-28T21:00:00-06:00
6 aired on 2010-12-05T21:00:00-06:00
You should always let Gson do the work for you. In this case you have an list of objects (map). So tell Gson to deserialize in that way and access to the structure using generic for loop and map access.

String s = response.toString();
JsonArray json = JsonArray.readFrom(s);
for (int i = 0; i < json.size(); i++) {
JsonObject show = json.get(i).asObject();
int episode = show.get("episode").asInt();
String time = show.get("first_aired_iso").asString();
System.out.println("Episode " + episode + " - " + time);
}
Thanks a lot HotLicks! :)

Related

mongo-java-driver update each item of array field belonging to document applying some conditional logic

I'm working on an event collection, where each document is modeled like so:
{
"event_name": "John Doe Concert",
"event_date": "2022-01-01"
"ticket_types": [
{
"name": "Front seats",
"total": 50 (we'll call this `oldTotal1`),
"available": 25 (we'll call this `oldAvailable1`)
},
{
"name": "Back seats",
"total": 100 (we'll call this `oldTotal2`),
"available": 50 (we'll call this `oldAvailable2`)
}
]
}
Suppose I have a REST API supporting a PUT endpoint which accepts a payload like this:
{
"event_name": "Jane Doe Concert",
"event_date": "2022-02-02"
"ticket_types": [
{
"name": "Front seats",
"total": 100 (we'll call this `newTotal1`),
},
{
"name": "Back seats",
"total": 150 (we'll call this `newTotal2`),
}
]
}
As you can see, I'm looking to update the document (doesn't matter if it's update or replace as long as the operation is atomic on a document level). For each element i in the ticket_types array in the payload, we can assume newTotal[i] >= oldTotal[i]
The way I'd like my document to look like after the update:
{
"event_name": "Jane Doe Concert",
"event_date": "2022-02-02"
"ticket_types": [
{
"name": "Front seats",
"total": 100 (the value of `newTotal1`),
"available": 75 (the value of `oldAvailable1` + `newTotal1` - `oldTotal1`)
},
{
"name": "Back seats",
"total": 150 (the value of `newTotal2`),
"available": 100 (the value of `oldAvailable2` + `newTotal2` - `oldTotal2`)
}
]
}
The problem I'm having is that I would like to perform the calculations of the resulting values of total and available exclusively through Mongo's findAndUpdate operation (without fetching the document first and doing the changes via Java code after so to speak). This is because the environment the code is run in is AWS Lambda, so I don't think I can rely on any locking mechanism other than the DB's own mechanisms, nor would I want to touch MongoDB's Transaction API.
My attempt so far:
final Document result = collection.findOneAndUpdate(query, Updates.combine(
Updates.set("event_name", request.getEventName()),
Updates.set("event_date", request.getDate().toString()),
// please help me!
Updates.set("ticket_types.$[elem].total", ...)
Updates.set("ticket_types.$[elem].available", ...)
Javascript equivalent should be:
db.getCollection("events").updateOne({name: 'John Doe Concert'},
{
$set: {
"ticket_types.$[first].total": 1000,
"ticket_types.$[first].available": "ticket_types.$[first].available" + 1000 - "ticket_types.$[first].total",
"ticket_types.$[second].total": 2000,
"ticket_types.$[second].available": "ticket_types.$[second].available" + 2000 - "ticket_types.$[second].total"
}
},
{
arrayFilters: [
{ "first.name": "Front seats" },
{ "second.name": "Back seats" }
]
}
)
Edit: The goal is to update the data doing calculation using existing attributes. I feel it's possible to achieve this using an update aggregation pipeline.
I am using DocumentDB 4.0 with application layer written in Java
Thanks

How to pull the last jsonPath value in Java?

Hello I wanted to ask how to retrieve the last value in a jsonPath
{
"testing": [
{
"transactionId": "5a99dcf84b7f633a5489805d",
"trackingId": "555112",
"tn": "6095555112",
"customerName": "John",
"customerLastName": "Chan"
},
{
"transactionId": "5a99dd3f4b7f633a54898068",
"tn": "6095555112",
"trackingId": "555112",
"customerName": "Amanda",
"customerLastName": "Brown"
}
]
}
My Java code Sample line
System.out.println("response.prettyPrint() = " + response.jsonPath().getString("testing.transactionId"));
Output
response.prettyPrint() = 5a99dcf84b7f633a5489805d,5a99dcf84b7f633a5489805d
Right now it is printing all transactionIds. It should be only pulling the latest one meaning the bottom one where transactionId = "5a99dd3f4b7f633a54898068"
If a new value come in (through back end logic, will add another set of values into this). How can I write a line that will pull the latest values set?
Example
{
"testing": [
{
"transactionId": "5a99dcf84b7f633a5489805d",
"trackingId": "555112",
"tn": "6095555112",
"customerName": "John",
"customerLastName": "Chan"
},
{
"transactionId": "5a99dd3f4b7f633a54898068",
"tn": "6095555112",
"trackingId": "555112",
"customerName": "Amanda",
"customerLastName": "Brown"
},
{
"transactionId": "newID",
"tn": "6095555112",
"trackingId": "555112",
"customerName": "Amanda",
"customerLastName": "Brown"
},
]
}
Now that a new dataset has been stored, How will I write a java code that would pull the transactionId "NewID"?
I don't want to hardcode and write something like ".transactionId[0]" [1] or [2]
Well instead of using getString you can use getList
For e.g
List<String> strList = response.jsonPath().getList("testing.transactionId");
System.out.println("last value is " + strList.get(strList.size()-1))
I hope this helps. I don't know the exact code but I know in an array you can get the last item like...
ARRAY.get(ARRAY.size()-1)
I am not sure how to properly implement that in your JSON array but I hope this sends you in the right direction.
With the Rest assured if you want to get the last item from array, you can use:
.extract()
.path("items[-1].value");

DynamoDB Nested Query for Set of Object

I have a table called Group and it will have records like:
{
"id": "UniqueID1",
"name": "Ranjeeth",
"emailIdMappings": [
{
"emailId": "r.pt#r.com",
"userId": 324
},
{
"emailId": "r1.pt#r.com",
"userId": 325
}
]
},
{
"id": "UniqueID2",
"name": "Ranjeeth",
"emailIdMappings": [
{
"emailId": "r1.pt#r.com",
"userId": 325
},
{
"emailId": "r2.pt#r.com",
"userId": 326
}
]
}
I need to query and get result if emailId contains the input string.
I have reached so far and I am not able to get the result
AttributeValue attributeValue = new AttributeValue("r.pt#r.com");
Condition containsCondition = new Condition()
.withComparisonOperator(ComparisonOperator.CONTAINS)
.withAttributeValueList(attributeValue);
Map<String, Condition> conditions = newHashMap();
conditions.put("emailIdMappings.emailId", containsCondition);
ScanRequest scanRequest = new ScanRequest()
.withTableName("Group")
.withScanFilter(conditions);
amazonDynamoDB.scan(scanRequest)
dynamoDBMapper.marshallIntoObjects(Group.class, scanResult.getItems());
For the above code I am expecting record with id UniqueID1, but it's empty. If you pass "r1.pt#r.com" then you should get both records.
sdk used is com.amazonaws:aws-java-sdk-dynamodb:1.11.155
I tried posting the question in aws forum which didn't help much.
As you have List of Objects which has two attributes in a object (i.e. emailId and userId), you need to provide both values in order to match the item.
The CONTAINS function will not be able to match the item if the object has two attributes and only one attribute value mentioned in the filter expression.
Otherwise, you need to provide the occurrence (i.e. index) of the list to match the item.
Example:-
emailIdMappings[0].emailId = :emailIdVal

Valid Json throws "Expected BEGIN_OBJECT but was STRING at line 1 column 4"

I know lot of people asked similars questions but, hell I'm stuck and I don't understand why. That's weird because the JSON is valid on jsonlint :
{
"Name": "Geography",
"Questions": [{
"_question": "Where is Max?",
"_answers": ["France", "USA", "Spain", "Tunisia"],
"_correctOne": 2,
"Asked": false,
"ID": 0
}, {
"_question": "Where is the Eiffel Tower?",
"_answers": ["Marseilles", "Le Mans", "Paris", "Lyon"],
"_correctOne": 3,
"Asked": false,
"ID": 1
}, {
"_question": "Where is Barcelona?",
"_answers": ["Italy", "Germany", "Portugual", "Spain"],
"_correctOne": 4,
"Asked": false,
"ID": 2
}, {
"_question": "Where is Malibu point?",
"_answers": ["San Francisco", "San Diego", "Los Angeles", "It\u0027s just in a movie"],
"_correctOne": 3,
"Asked": false,
"ID": 3
}, {
"_question": "Where takes place the famous 24h of Le Mans?",
"_answers": ["France", "Belgium", "Canada", "Martinique"],
"_correctOne": 1,
"Asked": false,
"ID": 4
}, {
"_question": "Which one of the following countries is the biggest one?",
"_answers": ["Mexico", "USA", "Russia", "India"],
"_correctOne": 3,
"Asked": false,
"ID": 5
}, {
"_question": "Where can you find a Camel?",
"_answers": ["Siberia", "Antartic", "Artic", "Sahara"],
"_correctOne": 4,
"Asked": false,
"ID": 6
}, {
"_question": "Where can\u0027t you find the statue of the liberty?",
"_answers": ["New York", "Paris", "Las Vegas", "Strasbourg"],
"_correctOne": 2,
"Asked": false,
"ID": 7
}, {
"_question": "What did Christophe Colomb has discovered?",
"_answers": ["Europe", "America", "Africa", "Asia"],
"_correctOne": 2,
"Asked": false,
"ID": 8
}, {
"_question": "Where can\u0027t you practice sky?",
"_answers": ["Maroco", "Canada", "Norway", "Dubaï"],
"_correctOne": 1,
"Asked": false,
"ID": 9
}, {
"_question": "Which one of the following countries isn\u0027t a neighboor of the France?",
"_answers": ["Germany", "Italy", "Spain", "Portugual"],
"_correctOne": 4,
"Asked": false,
"ID": 10
}]
}
So, it's just an ArrayList<Category>. Category is the following class:
public class Category {
public String Name;
public ArrayList<Question> Questions;
}
Also, the Question class below:
public class Question {
private String _question;
private String[] _answers;
private int _correctOne;
public boolean Asked;
public int ID;
}
Everything seems alright to me, I checked again and again, still have this error. However, something seems weird, each ' is replaced by \u0027, but it doesn't seems to be the problem..
I'm parsing the Gson from the following function:
public static boolean ReadCategoryFileTxt(Category category) {
try {
File file = new File(category.Name + ".txt");
Scanner sc = new Scanner(file);
String JSONString = "";
while (sc.hasNextLine())
JSONString += sc.nextLine();
Gson gson = new Gson();
Category _category = gson.fromJson(JSONString, Category.class);
category.Name = _category.Name;
category.Questions = _category.Questions;
//Debug.Println(gson.toJson(category, Category.class));
sc.close();
}
catch (Exception e)
{
Debug.PrintException(e);
return (false);
}
return (true);
}
Any idea for this "Expected BEGIN_OBJECT but was STRING at line 1 column 4"?
Thank in advance !
Looks the start of the JSON read from file is not open flower braces {
Point 1 - See if the file has any incorrect start characters
Point 2 - Set your text file encoding to UTF -8
Point 3 - Use String Builder instead of using + append assignment
Point 4 - If you have notepad++, you shall remove non-ascii characters using - Notepad++, How to remove all non ascii characters with regex?
public static boolean ReadCategoryFileTxt(Category category) {
try {
File file = new File(category.Name + ".txt");
Scanner sc = new Scanner(file);
StringBuilder JSONString = new StringBuilder;
while (sc.hasNextLine())
JSONString = JSONString.append(sc.nextLine());
Gson gson = new Gson();
Category _category = gson.fromJson(JSONString.toString().trim(), Category.class);
category.Name = _category.Name;
category.Questions = _category.Questions;
//Debug.Println(gson.toJson(category, Category.class));
sc.close();
}
catch (Exception e)
{
Debug.PrintException(e);
return (false);
}
return (true);
}
I'd like to leave a few words based on what you clarified in the comments. To be honest, I could not reproduce the exact exception with ... line 1 column 4 having ... line 1 column 1 instead, regardless the default JVM file.encoding property, but you're faced with a classic file encoding issue.
Your JSON is really well-formed.
Java promotes some naming conventions so _question and Asked appearing in the JSON can be expressed as #SerializedName("_question") String question; and #SerializedName("Asked") boolean isAsked; respectively.
\u0027 is an escaped character of '. Characters can be unescaped if they are a part of the enclosing document encoding. The apostrophe fits ASCII just perfect, however it may be escaped in order not to break JSON documents syntactically, say, string literals in JSON strings.
The real problem was that your JSON file was not invalid characters per se, but an UTF-8 encoded file with an explicit Byte Order Mark that should be processed before parsing begins to make sure that file content encoding is detected and decoded fine ( literally stands for UTF-8). UTF-aware editors just do not show BOMs since the latter are not considered bad or illegal characters, but use them to deal with UTF-encoded files (file encoding names are usually shown in statusbars, etc). That's why copying/pasting worked for you: BOMs were not included to copies (they "live" in files only, and in clipboard metadata I guess). By default, Java classes do not make any assumptions on the incoming file encoding leaving the decision on it on your own or even on user's own. It is described here. Therefore Gson should not process it and Gson really does not do it. All Gson can only consume is JSON tokens streams (and that's perfect design), so you have either to detect the input encoding, or let your user specify it.
You don't need to accumulate an intermediate String to parse a JSON: this is just memory wasting especially for big JSON documents. Gson can work in streaming manner, so it accepts Reader instances in order not to accumulate intermediate JSON strings reading a given input stream token by token trying to consume as less memory as possible. Also note that reading line by line is cheaper with BufferedReader rather than Scanner, however it's still discouraged for you case.
If you're using Java 7 or later, use try-with-resources to make sure your I/O resources are not leaked (otherwise use finally to make sure there are no resource leaks). Also it's worth noting that instantiating a Gson instance may be considered a little expensive operation, and since Gson instances are thread-safe and immutable, they can be instantiated once per application and shared globally (not necessarily a public static final Gson ..., of course, but something encapsulated elsewhere in a good design solution).
try( final Reader reader = new InputStreamReader(new FileInputStream(new File(category.Name + ".txt")), StandardCharsets.UTF_8)) {
Category _category = gson.fromJson(reader, Category.class);
category.Name = _category.Name;
category.Questions = _category.Questions;
//Debug.Println(gson.toJson(category, Category.class));
} catch ( Exception e ) {
Debug.PrintException(e);
return (false);
}
return (true);

Why do I always get JSON Exception?

This Is my first time with parsing JSON data. I am using the Google knowledge graph api. I got the api working and I can get the JSON result. This is Google 's sample return data for a sample query which I'm using now for testing.
{
"#context": {
"#vocab": "http://schema.org/",
"goog": "http://schema.googleapis.com/",
"resultScore": "goog:resultScore",
"detailedDescription": "goog:detailedDescription",
"EntitySearchResult": "goog:EntitySearchResult",
"kg": "http://g.co/kg"
},
"#type": "ItemList",
"itemListElement": [
{
"#type": "EntitySearchResult",
"result": {
"#id": "kg:/m/0dl567",
"name": "Taylor Swift",
"#type": [
"Thing",
"Person"
],
"description": "Singer-songwriter",
"image": {
"contentUrl": "https://t1.gstatic.com/images?q=tbn:ANd9GcQmVDAhjhWnN2OWys2ZMO3PGAhupp5tN2LwF_BJmiHgi19hf8Ku",
"url": "https://en.wikipedia.org/wiki/Taylor_Swift",
"license": "http://creativecommons.org/licenses/by-sa/2.0"
},
"detailedDescription": {
"articleBody": "Taylor Alison Swift is an American singer-songwriter and actress. Raised in Wyomissing, Pennsylvania, she moved to Nashville, Tennessee, at the age of 14 to pursue a career in country music. ",
"url": "http://en.wikipedia.org/wiki/Taylor_Swift",
"license": "https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License"
},
"url": "http://taylorswift.com/"
},
"resultScore": 896.576599
}
]
}
So I want to parse it so that I can get the name, description, detailed description. This is my code but I always seem to get the exception. Any ideas why?
try {
JSONObject object=new JSONObject(gggg);
JSONArray itemListElement = object.getJSONArray("itemListElement");
for(int i=0; i < itemListElement.length();i++){
JSONObject c = itemListElement.getJSONObject(i);
JSONObject results = c.getJSONObject("result");
String name = results.getString("name").toString();
String description = results.getString("description").toString();
String detailedDescription = results.getString("articleBody").toString();
gggg = "Name: "+name+"\n Description: "+description+"\n "+detailedDescription;
}
responseView.append(gggg);
} catch (JSONException e) {
Toast.makeText(MainActivity.this,gggg,Toast.LENGTH_LONG).show();
}
Also the string gggg contains the JSON data. I don't know why but I am always getting the exception. Please tell me what is the error in my code and how to repair it.
Thanks.
"Name: Taylor Swift Description: Singer-songwriter Taylor Alison
Swift is an American singer-songwriter and actress. Raised in
Wyomissing, Pennsylvania, she moved to Nashville, Tennessee, at the
age of 14 to pursue a career in country music. "
The problem is your String detailedDescription line.
You need to get the detailedDescription object before you retrieve the articleBody.
for(int i=0; i < itemListElement.length();i++){
JSONObject c = itemListElement.getJSONObject(i);
JSONObject results = c.getJSONObject("result");
String name = results.getString("name");
String description = results.getString("description");
JSONObject detailedDescription = results.getJSONObject("detailedDescription");
String articleBody = detailedDescription.getString("articleBody");
String x = "Name: "+name+"\n Description: "+description+"\n "+articleBody;
}
Also your .toString() method calls are redundant as you are calling .getString() on the JSON object.
With in the android json library it has a method called has element, which returns true or false. After successfully checking then access the element. The expection be caused by tring to access an element that isn't there.
Might be worth printing out after each time you create a new object to ensure that the objects are being created. It will also piont to where the expection is happening.

Categories