JSON Null Pointer Exception in Array with Jackson ObjectMapper - java

I am getting an array size of zero for the "tweets" array when trying to access the arraylist that it should be stored in. I am using Jackon databinding to a class, which at this point has "worked" as in not gave any errors or exceptions. But, the problem is still that the array is returning empty.
Here is the method where I am accessing the class that the JSON is being binded to:
WeatherDatabaseCreator.java
//Read in files to be parsed.
for (int i = 0; i < twitterFiles.size(); i++) {
File twitterFile = twitterFiles.get(i);
WeatherTweetParser wtp = new WeatherTweetParser(twitterFile);
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
System.out.print(tweets.size());
tweetIndex = 0;
System.out.println("Parsing and inserting twitter file '" + twitterFile.getAbsolutePath() + "'...");
//Step through all the tweets in each file, using the TweetParser class.
while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
numParsed++;
Boolean success = wdbm.insertTweet(tweet, user);
if (success == true) {
numInserted++;
}
if (entity.getNumHashtags() > 0){
for (int j = 0; j < entity.getNumHashtags(); j++) {
wdbm.insertHashtag(tweet, hashtags.get(j));
}
}
if (entity.getNumUserMentions() > 0) {
for (int k = 0; k < entity.getNumUserMentions(); k++) {
wdbm.insertReference(tweet, userMentions.get(k));
}
}
if (numParsed % UPDATE_INTERVAL == 0) {
System.out.println(numParsed + " tweets parsed. " + numInserted + " tweets inserted into database...");
}
tweetIndex++;
}
Here is part of the JSON File. The file is made up of an array of tweets, with some nested classes. Here I included two elements of the array:
2014-01-03-11-03.terms.json
{
"tweets": [
{
"filter_level": "medium",
"contributors": null,
"text": "U know your ice fishing at home when ur snacks are sandwiches,chips,dips,beef jerky and all the goodies instead of just a case of beer #mom",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
{
"text": "mom",
"indices": [
135,
139
]
}
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137025376145408,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137025376145408",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": true,
"statuses_count": 5411,
"lang": "en",
"profile_link_color": "17EBCF",
"profile_banner_url": "https://pbs.twimg.com/profile_banners/408240224/1384838946",
"id": 408240224,
"following": null,
"protected": false,
"favourites_count": 4222,
"profile_text_color": "333333",
"description": "It is what it is, no more, no less. Trust in the Lord. BSU Softball #5. My whole being is happy - Psalm 16:9",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "FFFFFF",
"name": "Nicole Anne",
"profile_background_color": "C0DEED",
"created_at": "Wed Nov 09 05:03:58 +0000 2011",
"default_profile_image": false,
"followers_count": 452,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"geo_enabled": true,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"follow_request_sent": null,
"url": null,
"utc_offset": -32400,
"time_zone": "Alaska",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 634,
"profile_sidebar_fill_color": "DDEEF6",
"screen_name": "NDupay",
"id_str": "408240224",
"profile_image_url": "http://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"listed_count": 1,
"is_translator": false
},
"coordinates": null
},
{
"filter_level": "medium",
"contributors": null,
"text": "Just watched DeBlasio shovel snow for the cameras and I have to say, his form is terrible. Looks a bit inexperienced.",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137026458673152,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137026458673152",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": false,
"statuses_count": 2609,
"lang": "en",
"profile_link_color": "FF8000",
"id": 163686045,
"following": null,
"protected": false,
"favourites_count": 204,
"profile_text_color": "333333",
"description": "Love learning, Hockey #NYR, music and photography. My family is my whole life.",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "EEEEEE",
"name": "Steven Marques",
"profile_background_color": "ACDED6",
"created_at": "Wed Jul 07 01:26:25 +0000 2010",
"default_profile_image": false,
"followers_count": 56,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"geo_enabled": false,
"profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
"profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
"follow_request_sent": null,
"url": null,
"utc_offset": -18000,
"time_zone": "Eastern Time (US & Canada)",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 58,
"profile_sidebar_fill_color": "F6F6F6",
"screen_name": "SMGafanha",
"id_str": "163686045",
"profile_image_url": "http://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"listed_count": 2,
"is_translator": false
},
"coordinates": null
},
Here is the Java class that the JSON file is mapped to, followed by the class mapping the JSON to the class:
Tweets.java
public class Tweets {
private ArrayList<Tweet> tweets;
public Tweets() {
tweets = new ArrayList<Tweet>();
}
public ArrayList<Tweet> getTweets() {
return tweets;
}
public void setTweets(ArrayList<Tweet> tweets) {
this.tweets = tweets;
}
public static class Tweet {
private String text;
#JsonProperty("source")
private String postMethod;
#JsonProperty("created_at")
private String time;
#JsonProperty("id")
private String ID;
public Tweet() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getID() {
return ID;
}
public void setID(String iD) {
ID = iD;
}
public String getPostMethod() {
return postMethod;
}
public void setPostMethod(String postMethod) {
this.postMethod = postMethod;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public class User {
private String location;
#JsonProperty("screen_name")
private String user;
#JsonProperty("time_zone")
private String timeZone;
#JsonProperty("description")
private String accountDescription;
public User(){
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getAccountDescription() {
return accountDescription;
}
public void setAccountDescription(String accountDescription) {
this.accountDescription = accountDescription;
}
}
public class Entities {
#JsonProperty("user_mentions")
ArrayList<UserMention> userMentions;
#JsonProperty("hashtags")
ArrayList<Hashtag> hashtags;
public Entities() {
}
public ArrayList<UserMention> getUserMentions() {
return userMentions;
}
public int getNumUserMentions() {
return userMentions.size();
}
public UserMention getUserMention(int index) {
return userMentions.get(index);
}
public void setUserMentions(ArrayList<UserMention> userMentions) {
this.userMentions = userMentions;
}
public ArrayList<Hashtag> getHashtags() {
return hashtags;
}
public int getNumHashtags() {
return hashtags.size();
}
public Hashtag getHashtag(int index) {
return hashtags.get(index);
}
public void setHashtags(ArrayList<Hashtag> hashtags) {
this.hashtags = hashtags;
}
public class UserMention {
#JsonProperty("screen_name")
private String userRef;
public UserMention() {
}
public String getUserRef() {
return userRef;
}
public void setUserRef(String userRef) {
this.userRef = userRef;
}
}
public class Hashtag {
#JsonProperty("text")
private String hashText;
public Hashtag() {
}
public String getHashText() {
return hashText;
}
public void setHashText(String hashText) {
this.hashText = hashText;
}
}
}
}
}
WeatherTweetParser.java
public class WeatherTweetParser {
private static File twitterFile;
public WeatherTweetParser(File twitterFile) {
WeatherTweetParser.twitterFile = twitterFile;
}
public void mapJavaObject() {
String jsonFile = twitterFile.getName();
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
}
And here is the error:
Mapping JSON to WeatherTweet Class.
Finished Mapping of JSON File.
Tweets size: 0
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at database.WeatherDatabaseCreator.main(WeatherDatabaseCreator.java:145)
Parsing and inserting twitter file 'C:\Users\Jared\Documents\Eclipse
WorkSpace\workspace\WeatherDatabaseCreator\2014-01-03-11-03.terms.json'...
On this line of WeatherDatabaseCreator.java:
tweet = tweets.get(tweetIndex);
TL:DR: I understand this error is because the index is out of range, because there is nothing obviously even in the tweets array. But, if the Jackson mapping of the JSON file to my Java Class went through without exceptions, why is the tweets array empty?

while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
The only break in this loop will work only if getText is null. If getText is not null for all the tweets, you'll get index out of bound exception.
Instead of while(true) you should probably use a check like tweetIndex < tweets.size()
The second problem. You create a Tweets object without loading any items there:
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
Of course tws object will not have any tweets in this case. What you need to do is to make sure that your mapJavaObjects() method returns a Tweets object with the tweets loaded by ObjectMapper and after this is done your code should look like this:
tweets = wtp.mapJavaObject();
Something like this:
public Tweets mapJavaObject() {
String jsonFile = twitterFile.getName();
Tweets ret = null;
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
ret = (Tweets) mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
retrun ret;
}

Related

How to Find Groups Based on uids by when using two different ArrayLists?

Using Java 1.8 and Spring Boot 1.5.6.RELEASE.
Am able to obtain a list of items from by parsing /etc/passwd and /etc/group inside an ArrayList & ArrayList.
Need to create the following Rest Endpoint:
HTTP GET /users/<uid>/groups
Return all the groups for a given user.
User:
public class User {
String name;
String password;
Integer uid;
Integer gid;
String comment;
String home;
String shell;
public User(String line) {
String[] items = line.split(":");
if (items.length != 7) {
throw new IllegalArgumentException("Need 7 items from " + line + " and there's only: " + items.length);
}
this.name = items[0];
this.password = items[1];
this.uid = Integer.parseInt(items[2]);
this.gid = Integer.parseInt(items[3]);
this.comment = items[4];
this.home = items[5];
this.shell = items[6];
}
// Getters & Setters omitted for brevity.
}
Group:
public class Group {
private Integer gid;
private String name;
private List<String> members;
public Group(String line) {
String[] items = line.split(":");
this.name = items[0];
this.gid = Integer.parseInt(items[2]);
if (items.length > 3){
this.members = Arrays.asList(items[3]);
}
}
// Getters & Setters omitted for brevity.
}
FileParserUtils:
public class FileParserUtils {
public static List<Group> parseFileForGroups(String line) {
List<Group> groups = null;
try (Stream<String> stream = Files.lines(Paths.get(line))) {
groups = stream.filter(s -> s.charAt(0) != '#').map(Group::new)
.collect(Collectors.toCollection(LinkedList::new));
}
catch (Exception e) {
e.printStackTrace();
}
return groups;
}
}
Service:
#Service
public class UserServiceImpl implements UserService {
#Override
public User findByUid(String line, Integer uid) {
List<User> allUsers = FileParserUtils.parseFileForUsers(line);
for (User user : allUsers) {
if (user.getUid() == uid) {
return user;
}
}
return null;
}
#Override
public List<Group> findByGroupsByUid(String line, Integer uid) {
User specificUser = findByUid(line, uid);
Integer userGid = specificUser.getGid();
List<Group> allGroups = FileParserUtils.parseFileForGroups(line);
List<Group> userGroups = new ArrayList<>();
for (Group group : allGroups) {
if (userGid == group.getGid()) {
userGroups.add(group);
}
}
return userGroups;
}
}
This issue is that not all User uids are the same as the Group's gids (see the gids & uids for "name":"_cyrus"):
Obtain a list of Users (along with their uids & gids):
HTTP GET /myservice/users:
Yields JSON Payload Response:
[
{
"name":"_cyrus",
"password":"*",
"uid":77,
"gid":6,
"comment":"Cyrus Administrator",
"home":"/var/imap",
"shell":"/usr/bin/false"
},
{
"name":"_mailman",
"password":"*",
"uid":78,
"gid":78,
"comment":"Mailman List Server",
"home":"/var/empty",
"shell":"/usr/bin/false"
},
{
"name":"_appserver",
"password":"*",
"uid":79,
"gid":79,
"comment":"Application Server",
"home":"/var/empty",
"shell":"/usr/bin/false"
},
{
"name": "_jabber",
"password": "*",
"uid": 84,
"gid": 84,
"comment": "Jabber XMPP Server",
"home": "/var/empty",
"shell": "/usr/bin/false"
}
]
Groups only have gids (and not uids):
[
{
"gid": 6,
"name": "mail",
"members": [
"_teamsserver"
]
}
{
"gid": 78,
"name": "_mailman",
"members": null
},
{
"gid": 79,
"name": "_appserverusr",
"members": null
},
{
"gid": 30,
"name": "_keytabusers",
"members": [
"_calendar,_jabber,_postfix"
]
}
]
So, when if I try to find all the groups that Jabber belongs to:
http://localhost:8080/MyService/users/84/groups
Get the following JSON Response Payload:
[
{
"gid": 84,
"name": "_jabber",
"members": [
"84",
"Jabber XMPP Server",
"/var/empty",
"/usr/bin/false"
]
}
]
Why is 84 inside the members JSON array?
This is supposed to return all groups for the given user:
[
{
"gid": 29,
"name": "certusers",
"members": [
"root,_jabber,_postfix,_cyrus,_calendar,_dovecot"
]
},
{
"gid": 30,
"name": "_keytabusers",
"members": [
"_calendar,_jabber,_postfix"
]
}
]
Is there a way to map (e.g. link the two ArrayLists together or is there a different data structure that would help me do this) the User.uids with Group.gids?
This is all in-memory so please don't mention the use of ORM or JDBC.

Parse JSON to fetch all the details using Asynctask

{
"response_code": 200,
"debit": 3,
"position": "Train has reached Destination and late by 5 minutes",
"train": {
"number": "12046",
"name": "CDG NDLS SHTBDI"
},
"route": [
{
"no": 1,
"day": 0,
"station": {
"name": "CHANDIGARH",
"code": "CDG"
},
"has_arrived": false,
"has_departed": true,
"distance": 0,
"scharr": "Source",
"schdep": "12:00",
"actarr": "00:00",
"actdep": "12:00",
"scharr_date": "19 Nov 2015",
"actarr_date": "19 Nov 2015",
"latemin": 0
},
{
"no": 2,
"day": 0,
"station": {
"name": "AMBALA CANT JN",
"code": "UMB"
},
"has_arrived": true,
"has_departed": true,
"distance": 67,
"scharr": "12:40",
"schdep": "12:42",
"actarr": "12:40",
"actdep": "12:42",
"scharr_date": "19 Nov 2015",
"actarr_date": "19 Nov 2015",
"latemin": 0
},
{
"no": 3,
"day": 0,
"station": {
"name": "NEW DELHI",
"code": "NDLS"
},
"has_arrived": true,
"has_departed": false,
"distance": 265,
"scharr": "15:25",
"schdep": "Destination",
"actarr": "15:30",
"actdep": "00:00",
"scharr_date": "19 Nov 2015",
"actarr_date": "19 Nov 2015",
"latemin": 5
}
]
}
public class TrainStatus {
public static int responseCode;
private int serialNo;
private String scheduleArrival;
private String actualArrival;
public static String station;
public static int debit;
private String statusOfArrival;
private boolean hasArrived;
private boolean hasDeparted;
private int latemin;
private String actualArrivalDate;
private String scheduleArrivalDate;
public static String position;
public String name;
public String getName()
{
return getName();
}
public void setName(String name)
{
this.name=name;
}
public boolean isHasArrived()
{
return hasArrived;
}
public void setHasArrived(boolean hasArrived)
{
this.hasArrived = hasArrived;
}
public boolean isHasDeparted()
{
return hasDeparted;
}
public void setHasDeparted(boolean hasDeparted)
{
this.hasDeparted = hasDeparted;
}
public int getLatemin()
{
return latemin;
}
public void setLatemin(int latemin)
{
this.latemin = latemin;
}
public void setSerialNo(int serialNo)
{
this.serialNo = serialNo;
}
public String getScheduleArrival()
{
return scheduleArrival;
}
public void setScheduleArrival(String scheduleArrival)
{
this.scheduleArrival = scheduleArrival;
}
public String getActualArrival()
{
return actualArrival;
}
public void setActualArrival(String actualArrival)
{
this.actualArrival = actualArrival;
}
public String getStation()
{
return station;
}
public void setStation(String station)
{
this.station = station;
}
public String getStatusOfArrival()
{
return statusOfArrival;
}
public void setStatusOfArrival(String statusOfArrival)
{
this.statusOfArrival = statusOfArrival;
}
public String getActualArrivalDate()
{
return actualArrivalDate;
}
public void setActualArrivalDate(String actualArrivalDate)
{
this.actualArrivalDate = actualArrivalDate;
}
public String getScheduleArrivalDate()
{
return scheduleArrivalDate;
}
public void setScheduleArrivalDate(String scheduleArrivalDate)
{
this.scheduleArrivalDate = scheduleArrivalDate;
}
}
public class TrainStatusParser {
public static List<TrainStatus> parseFeed(String content){
try
{
JSONObject jsonObject = new JSONObject(content);
List<TrainStatus> trainList = new ArrayList<>();
TrainStatus.responseCode = jsonObject.getInt("response_code");
TrainStatus.position = jsonObject.getString("position");
TrainStatus.debit=jsonObject.getInt("debit");
JSONArray route = jsonObject.getJSONArray("route");
for(int i=0;i<route.length();i++)
{
JSONObject routeObject = route.getJSONObject(i);
TrainStatus trainStatus = new TrainStatus();
if (jsonObject.has("station"))
{
JSONObject addressObject = jsonObject.getJSONObject("station");
trainStatus.name=addressObject.getString("name");
}
trainStatus.setSerialNo(routeObject.getInt("no"));
trainStatus.setScheduleArrival(routeObject.getString("scharr"));
trainStatus.setActualArrival(routeObject.getString("actarr"));
trainStatus.setStatusOfArrival(routeObject.getString("status"));
trainStatus.setHasArrived(routeObject.getBoolean("has_arrived"));
trainStatus.setHasDeparted(routeObject.getBoolean("has_departed"));
trainStatus.setLatemin(routeObject.getInt("latemin"));
trainStatus.setActualArrivalDate(routeObject.getString("actarr_date"));
trainStatus.setScheduleArrivalDate(routeObject.getString("scharr_date"));
trainList.add(trainStatus);
}
return trainList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
Everything is correctly fetched except station name
Try this following code.
for(int i=0;i<route.length();i++) {
JSONObject routeObject = route.getJSONObject(i);
TrainStatus trainStatus = new TrainStatus();
JSONObject jsonObject_station = routeObject.getJSONObject("station");
String stationname = jsonObject_station.getString("name");
String code = jsonObject_station.getString("code");
Log.d("checkvalue", " " + stationname + " " + code);
trainStatus.setSerialNo(routeObject.getInt("no"));
trainStatus.setScheduleArrival(routeObject.getString("scharr"));
trainStatus.setActualArrival(routeObject.getString("actarr"));
trainStatus.setStatusOfArrival(routeObject.getString("status"));
trainStatus.setHasArrived(routeObject.getBoolean("has_arrived"));
trainStatus.setHasDeparted(routeObject.getBoolean("has_departed"));
trainStatus.setLatemin(routeObject.getInt("latemin"));
trainStatus.setActualArrivalDate(routeObject.getString("actarr_date"));
trainStatus.setScheduleArrivalDate(routeObject.getString("scharr_date"));
trainList.add(trainStatus);
}
Use a library from Google call GSON
In your posted code for parsing each route, you have this:
JSONObject routeObject = route.getJSONObject(i);
TrainStatus trainStatus = new TrainStatus();
if (jsonObject.has("station"))
{
JSONObject addressObject = jsonObject.getJSONObject("station");
trainStatus.name=addressObject.getString("name");
}
Looks like a typo here is causing your problems. You're calling jsonObject.has("station") when you should instead be calling routeObject.has("station"). Similarly, inside the if statement you should change jsonObject.getJSONObject("station") to routeObject.getJSONObject("station").

All json objects get updated on text change?

This is my log for the 1st text change
[{
"custInfo": "Anup 8600931386",
"rate": "24032",
"weight": "21.00000",
"makingAmt": "232",
"description": "GENTS ANGTHI 22k NO STONE",
"sum_total": "50954.4",
"vat": "",
"itemTotal": "50954.4",
"barcode": "BQSP78BB",
"net_rate": "24264.0",
"date": "09-12-2015",
"invoiceNo": "1",
"bill_type": "Estimate"
}]
Now when I add one more entry the previous item also gets updated.This is the log after the 2nd entry.
[{
"custInfo": "Anup 8600931386",
"rate": "24052",
"weight": "12.00000",
"makingAmt": "228",
"description": "LADIES TOP 22K NO STONE",
"sum_total": "29136.0",
"vat": "",
"itemTotal": "29136.0",
"barcode": "BQSP82BB",
"net_rate": "24280.0",
"date": "09-12-2015",
"invoiceNo": "1",
"bill_type": "Estimate"
}, {
"custInfo": "Anup 8600931386",
"rate": "24052",
"weight": "12.00000",
"makingAmt": "228",
"description": "LADIES TOP 22K NO STONE",
"sum_total": "29136.0",
"vat": "",
"itemTotal": "29136.0",
"barcode": "BQSP82BB",
"net_rate": "24280.0",
"date": "09-12-2015",
"invoiceNo": "1",
"bill_type": "Estimate"
}]
This is my text watcher implementation and the code that updates the values is inside after text changed().
private TextWatcher mkAmountTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
String mkAmt = makingAmount.getText().toString();
mk = Double.parseDouble(mkAmt);
calculateAndShow(wt, rt, mk);
int mid = (int) newRow.getTag()-1;
if ((mid<0) || (mid>itemSelectedJson.length())){
return;
}
try{
itemSelectedJson.getJSONObject(mid).put("makingAmt",mkAmt);
Log.d("MAKING_TW", itemSelectedJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
};
This is the code for creating the json array.
private void createJsonArray() {
billType = (invEstSwitch.isChecked() ? textViewEstimate : textViewInvoice)
.getText().toString();
String invNumber = textViewInvNo.getText().toString();
String bcode = barCode.getText().toString();
String description = itemDesc.getText().toString();
String wt = weightLine.getText().toString();
String rateAmt = rateAmount.getText().toString();
String making = makingAmount.getText().toString();
String netr = netRate.getText().toString();
String iTotal = itemtotal.getText().toString();
String vatAmt = textViewVat.getText().toString();
String sumAmt = textViewSum.getText().toString();
String crtDate = textViewCurrentDate.getText().toString();
try {
jsonObject.put("custInfo", custSelected.toString());
jsonObject.put("invoiceNo", invNumber);
jsonObject.put("barcode", bcode);
jsonObject.put("description", description);
jsonObject.put("weight", wt);
jsonObject.put("rate", rateAmt);
jsonObject.put("makingAmt", making);
jsonObject.put("net_rate", netr);
jsonObject.put("itemTotal", iTotal);
jsonObject.put("vat", vatAmt);
jsonObject.put("sum_total", sumAmt);
jsonObject.put("bill_type", billType);
jsonObject.put("date", crtDate);
} catch (JSONException e) {
e.printStackTrace();
}
try {
itemSelectedJson.put(index, jsonObject);
index++;
} catch (JSONException e) {
e.printStackTrace();
}
}
In this Method createJsonArray() you are not using same JSONObject every time. That's why you are getting same content again and again.
Just try to initialize jsonObject in createJsonArray() method first, then I guess, it will work.

Parse nested custom object array using jackson and parcelable

I am trying to parse a JSON into Java Bean using Jackson.
Snippet of JSON on Server Side:
{
"count": 17,
"next": null,
"previous": null,
"results": [
{
"resource_uri": "http://www.randomsite.com/api/1/personalize/qna/17/",
"answer_set": [],
"answers_count": 0,
"tags": [
"Others"
],
"title": "How many boys hostels are there is ACMS , which one is the best one",
"desc": "How many boys hostel are there in ACMS and which one is good among them, How can i get them, Do i have to apply early or can apply any any time in session. ",
"status": 1,
"is_spam": false,
"upvotes": 0,
"downvotes": 0,
"view_count": 4,
"uri_slug": "how-many-boys-hostels-are-there-is-acms-which-one-is-the-best-one",
"added_on": "2015-06-05T16:43:26",
"user": "http://www.randomsite.com/api/1/users/1/",
"degree": null,
"stream": "http://www.randomsite.com/api/1/streams/16/",
"institute": null,
"course": null,
"city": null,
"state": null
},
{
"resource_uri": "http://www.randomsite.com/api/1/personalize/qna/18/",
"answer_set": [
{
"id": 5,
"resource_uri": "http://www.randomsite.com/api/1/personalize/answers/5/",
"question": "http://www.randomsite.com/api/1/personalize/qna/18/",
"answer_text": "You will get purified water, volley ball court, cricket ground, gymnasium, tt, carrom , chess, parking, mess, canteen",
"status": 1,
"is_spam": false,
"upvotes": 0,
"downvotes": 0,
"best_answer": false,
"added_on": "2015-06-05T17:00:26",
"user": "http://www.randomsite.com/api/1/users/1/"
},
{
"id": 6,
"resource_uri": "http://www.randomsite.com/api/1/personalize/answers/6/",
"question": "http://www.randomsite.com/api/1/personalize/qna/18/",
"answer_text": "You can call your friends over there but girls are not allowed.",
"status": 1,
"is_spam": false,
"upvotes": 0,
"downvotes": 0,
"best_answer": false,
"added_on": "2015-06-05T17:00:26",
"user": "http://www.randomsite.com/api/1/users/1/"
}
],
"answers_count": 2,
"tags": [],
"title": "Girls are allowed in boys hostels of ACMS",
"desc": "If I manage to get Boys hostel in ACMS what are the faciclities that i will get, can i call my friends there which include girls.",
"status": 1,
"is_spam": false,
"upvotes": 0,
"downvotes": 2,
"view_count": 106,
"uri_slug": "girls-are-allowed-in-boys-hostels-of-acms",
"added_on": "2015-06-05T16:43:53",
"user": "http://www.randomsite.com/api/1/users/1/",
"degree": null,
"stream": null,
"institute": null,
"course": null,
"city": null,
"state": null
}
}
This is the Questions Entity class:
public class QnAQuestions implements Parcelable {
public static final Creator<QnAQuestions> CREATOR = new Creator<QnAQuestions>() {
#Override
public QnAQuestions createFromParcel(Parcel source) {
return new QnAQuestions(source);
}
#Override
public QnAQuestions[] newArray(int size) {
return new QnAQuestions[size];
}
};
public String resource_uri;
public ArrayList<QnAAnswers> answer_set;
public int answers_count;
public ArrayList<String> tags;
public String title;
public String desc;
public int status;
public boolean is_spam;
public int upvotes;
public int downvotes;
public int view_count;
public String uri_slug;
public String added_on;
public String user;
public String degree;
public String stream;
public String institute;
public String course;
public String city;
public String state;
public QnAQuestions() {
//answer_set = new ArrayList<QnAAnswers>();
}
public QnAQuestions(Parcel source) {
resource_uri = source.readString();
answers_count = source.readInt();
title = source.readString();
desc = source.readString();
status = source.readInt();
tags = source.createStringArrayList();
is_spam = source.readString() == "true";
upvotes = source.readInt();
downvotes = source.readInt();
view_count = source.readInt();
uri_slug = source.readString();
added_on = source.readString();
user = source.readString();
degree = source.readString();
stream = source.readString();
institute = source.readString();
course = source.readString();
city = source.readString();
state = source.readString();
//answer_set = new ArrayList<QnAAnswers>();
answer_set = source.createTypedArrayList(QnAAnswers.CREATOR);
source.readTypedList(answer_set, QnAAnswers.CREATOR);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(resource_uri);
dest.writeInt(answers_count);
dest.writeString(title);
dest.writeString(desc);
dest.writeInt(status);
dest.writeStringList(tags);
dest.writeInt(is_spam ? 1 : 0);
dest.writeInt(upvotes);
dest.writeInt(downvotes);
dest.writeInt(view_count);
dest.writeString(uri_slug);
dest.writeString(added_on);
dest.writeString(user);
dest.writeString(degree);
dest.writeString(stream);
dest.writeString(institute);
dest.writeString(city);
dest.writeString(state);
dest.writeTypedList(answer_set);
}
}
And this is Answers Class:
public class QnAAnswers implements Parcelable {
public static final Creator<QnAAnswers> CREATOR = new Creator<QnAAnswers>() {
#Override
public QnAAnswers createFromParcel(Parcel source) {
return new QnAAnswers(source);
}
#Override
public QnAAnswers[] newArray(int size) {
return new QnAAnswers[size];
}
};
public long id;
public String resource_uri;
public String question;
public String answer_text;
public int status;
public boolean is_spam;
public int upvotes;
public int downvotes;
public boolean best_answer;
public String added_on;
public String user;
public QnAAnswers() {}
public QnAAnswers(Parcel source) {
id = source.readLong();
resource_uri = source.readString();
question = source.readString();
answer_text = source.readString();
status = source.readInt();
is_spam = source.readString() == "true";
upvotes = source.readInt();
downvotes = source.readInt();
best_answer = source.readString() == "true";
added_on = source.readString();
user = source.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(resource_uri);
dest.writeString(question);
dest.writeString(answer_text);
dest.writeInt(status);
dest.writeInt(is_spam ? 1 : 0);
dest.writeInt(upvotes);
dest.writeInt(downvotes);
dest.writeInt(best_answer ? 1 : 0);
dest.writeString(added_on);
dest.writeString(user);
}
}
I am only able to see the fields pertaining to QnAAnswers Class. All other fields are not populated.
This is the code in the activity which parses the API response and displays the QnAFragment:
private void showQnAQuestions(String response) {
try {
String questions = extractResults(response);
List<QnAQuestions> qnAQuestions = JSON.std.listOfFrom(QnAQuestions.class, questions);
displayFragment(QnAQuestionsListFragment.newInstance(new ArrayList<>(qnAQuestions)), false);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
private String extractResults(String response) {
try {
// JsonFactory jf = new JsonFactory();
//Result r = Result.createFromJson(jf.createParser(json2));
Map<String, Object> map = JSON.std.mapFrom(response);
if (map.get("next") != null)
next = map.get("next").toString();
else
next = null;
return JSON.std.asString(map.get("results"));
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
return null;
}
Any pointers would do great help!!
First thing I noticed, you read:
is_spam = source.readString() == "true"
but you write is_spam as 1 or 0 into the Parcel:
dest.writeInt(is_spam ? 1 : 0);
Same for best _ answer.

Java JSON parsing for subclass objects

I am able to write to a JSON file. Why is it that, if I write another object from a different subclass, the JSON file will be rewritten and only display fields for that new subclass....previous entries will be deleted...
Example:
//evt is an ArrayList<Event> list
//evt contains a list of objects of type TimedEvent
//TimedEvent extends Event class
//Event is the abstract class
toJson("C://myJson.json", evt);
The above will generate this:
[
{
"eventStartDateTime": {
"year": 2014,
"month": 3,
"dayOfMonth": 11,
"hourOfDay": 11,
"minute": 5,
"second": 0
},
"eventEndDateTime": {
"year": 2014,
"month": 3,
"dayOfMonth": 11,
"hourOfDay": 12,
"minute": 5,
"second": 0
},
"title": "My First Event",
"eventId": "2u0-zBGhkdX8FcbFCFp3ah",
"completed": false
}
]
But if I change the list to a different object from a different subclass, the previous fields in the first JSON file disappears.
//evt is an ArrayList<Event> list
//evt this time contains a list of objects of type FloatingEvent
//FloatingEvent also extends Event class
toJson("C://myJson.json", evt);
The above will generate this:
[
{
"title": "My First Event",
"eventId": "2u0-zBGhkdX8FcbFCFp3ah",
"completed": false
},
{
"title": "My Second Event",
"eventId": "19Jv07-a4ICaex.8fceZOc",
"completed": false
}
]
How can I make sure that the method toJson appends the new event but keep whatever fields written the first time.
What I need is something like this..isit possible??....how do I separate the two objects then when retrieving?
[
{
"eventStartDateTime": {
"year": 2014,
"month": 3,
"dayOfMonth": 11,
"hourOfDay": 11,
"minute": 5,
"second": 0
},
"eventEndDateTime": {
"year": 2014,
"month": 3,
"dayOfMonth": 11,
"hourOfDay": 12,
"minute": 5,
"second": 0
},
"title": "My First Event",
"eventId": "2u0-zBGhkdX8FcbFCFp3ah",
"completed": false
},
{
"title": "My Second Event",
"eventId": "19Jv07-a4ICaex.8fceZOc",
"completed": false
}
]
The code I used to write the JSON file:
public static String toJson(String fileName, List<Event> evt) {
fileName = Utilities.getDefaultFileName();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = "";
try {
File file = new File(fileName);
// if file does not exists, then create it
if (!file.exists()) {
json = gson.toJson(evt);
file.createNewFile();
FileWriter writer = new FileWriter(fileName);
writer.write(json);
writer.close();
} else {
ArrayList<Event> currentEventList = fromJson(fileName);
for (Event newEvent : evt) {
currentEventList.add(newEvent);
}
json = gson.toJson(currentEventList);
file.delete();
file.createNewFile();
FileWriter writer = new FileWriter(fileName);
writer.write(json);
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println(Language.getString("ERROR_CONVERT_DATA_OBJECT"));
}
return fileName;
}
The code I used to retrieve the list of events from the JSON file:
public static ArrayList<Event> fromJson(String fileName) {
ArrayList<Event> list = new ArrayList<Event>();
try {
Gson gson = new Gson();
Event[] myTypes = gson.fromJson(new FileReader(fileName),
Event[].class);
for (int i = 0; i < myTypes.length; i++) {
list.add(i, myTypes[i]);
}
} catch (JsonSyntaxException e) {
e.printStackTrace();
} catch (JsonIOException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out
.println(Language.getString("ERROR_MISSING_DEFAULT_FILE"));
}
return list;
}
The Event class:
public class Event {
protected String title;
protected String eventId;
protected String eventDescription;
protected boolean completed;
//
public Event() {
setEventId();
completed = false;
}
//
public String getEventId() {
return eventId;
}
public void setEventId() {
this.eventId=Utilities.generateUniqueIdentification();
}
//
public String getEventDescription() {
return eventDescription;
}
public void setEventDescription(String eventDescription) {
this.eventDescription = eventDescription;
}
//
public boolean getCompleted() {
return completed;
}
//
public void setCompleted() {
completed = true;
}
//
public void setUncompleted() {
completed = false;
}
//
/**
* This method returns the title of an event.
* #return Returns event title.
*/
public String getTitle() {
return title;
}
//
/**
* This method sets the title of an event.
* #param title The title of this event.
*/
public void setTitle(String title) {
this.title = title;
}
}
The TimedEvent class:
import java.util.Calendar;
public class TimedEvent extends Event {
protected Calendar eventStartDateTime;
protected Calendar eventEndDateTime;
public TimedEvent(String title, Calendar eventStartDateTime,
Calendar eventEndDateTime) {
super();
this.title = title;
this.eventStartDateTime = eventStartDateTime;
this.eventEndDateTime = eventEndDateTime;
}
public Calendar getEventStartDateTime() {
return eventStartDateTime;
}
public void setEventStartDateTime(Calendar eventStartDateTime) {
this.eventStartDateTime = eventStartDateTime;
}
public Calendar getEventEndDateTime() {
return eventEndDateTime;
}
public void setEventEndDateTime(Calendar eventEndDateTime) {
this.eventEndDateTime = eventEndDateTime;
}
}
The FloatingEvent class:
public class FloatingEvent extends Event{
//
public FloatingEvent(String title){
super();
setTitle(title);
setEventId();
}
}
You have to call the method toJson only once, by passing a list of Events that contains objects that can be either TimedEvents or FloatingEvent.

Categories

Resources