JSONArray cannot be converted to JSONObject exception - java

I have a JSON String structured in the following way and it throws an exception passing it into JSONArray timeJSONArray = new JSONArray(time);
This is the error Value [{"daysByte":158,"from":1020,"to":1260},{"daysByte":96,"from":1020,"to":1320}] at 0 of type org.json.JSONArray cannot be converted to JSONObject This is how I receive the array and I can't change it, so I'm having trouble converting it to a JSON Object instead of a JSON String which is the format it's currently in. What am I doing wrong?
[
[
{
"daysByte":30,
"from":660,
"to":1290
},
{
"daysByte":96,
"from":660,
"to":1320
},
{
"daysByte":128,
"from":1050,
"to":1290
}
],
[
{
"daysByte":252,
"from":690,
"to":840
},
{
"daysByte":252,
"from":1050,
"to":1260
}
]
]
This is the code I am working with. I'm getting the value passed in as a string
public ArrayList<String> getTimeList(String time){
System.out.println("PLACES ACTIVITY " + time);
ArrayList<String> times = new ArrayList<>();
try{
//JSONObject timeJSONObject = new JSONObject(time);
JSONArray timeJSONArray = new JSONArray(time);
ArrayList<LegacyTimeSpan> timeSpanList = new ArrayList<>();
LegacyTimeSpanConverterImpl converter = new LegacyTimeSpanConverterImpl();
for(int i = 0; i < timeJSONArray.length(); i++){
int daysByte = timeJSONArray.getJSONObject(i).getInt("daysByte");
int from = timeJSONArray.getJSONObject(i).getInt("from");
int to = timeJSONArray.getJSONObject(i).getInt("to");
System.out.println("TO " + to);
LegacyTimeSpan timeSpan = new LegacyTimeSpan(daysByte, from, to);
timeSpanList.add(timeSpan);
}
Log.d("Time span list", timeSpanList.toString());
WeekSpan weekSpan = converter.convertToWeekSpan(timeSpanList);
List<DayTimeSpanPair> dayTimeSpanPair = weekSpan.toDayTimeSpanPairs();
for(int i = 0; i< dayTimeSpanPair.size(); i++){
String timeRange = buildTimeString(dayTimeSpanPair.get(i));
times.add(timeRange);
}
} catch(JSONException e){
Log.d("PLACES EXCEPTION JSON",e.getMessage());
}
return times;
}

This Code should work i think as u declare the json Format.
[
[
{
} ,{},{} // Json Object Structure as u defined in you Question
topArray = ],
[
{
},{},{}
]
]
for(JSONArray objArray : topArray){
for(JSONObject eachObject : objArray){
System.out.println(eachObject.get("daysByte"););
System.out.println(eachObject.get("from");
System.out.println(eachObject.get("to");
}
}

Hi following code is working for your json I have tried. It is specific for your json not generic. so if you want you can use it.
try{
JSONArray jsonArray = new JSONArray(data); //insted "Data" pass your json Strint
for(int i=0 ; i<jsonArray.length() ; i++){
JSONArray internalArray = jsonArray.getJSONArray(i);
for(int j = 0 ; j < internalArray.length() ; j++){
JSONObject internalObject = internalArray.getJSONObject(j);
Log.d("data" , internalObject.getString("daysByte"));
Log.d("data" , internalObject.getString("from"));
Log.d("data" , internalObject.getString("to"));
}
}
}catch(Exception e){
Log.d("data" ,"Error");
}
}

You have two arrays, one array within other.
You have to do like this:
for(JSONArray temp: timeJsonArray)
{
// try to convert to json object
}

It is a 2D Array.
System.out.println("days");
String content = new Scanner(new File("C:/day.txt")).useDelimiter("\\Z").next();
Day[][] customDayWrap = new Gson().fromJson(content, Day[][].class);
for (Day[] days : customDayWrap) {
for (Day day : days) {
System.out.println(day.getDaysByte());
System.out.println(day.getFrom());
System.out.println(day.getTo());
}
}
And your Day Class will be something like this.
public class Day {
#SerializedName("daysByte")
#Expose
private Integer daysByte;
#SerializedName("from")
#Expose
private Integer from;
#SerializedName("to")
#Expose
private Integer to;
/**
*
* #return
* The daysByte
*/
public Integer getDaysByte() {
return daysByte;
}
/**
*
* #param daysByte
* The daysByte
*/
public void setDaysByte(Integer daysByte) {
this.daysByte = daysByte;
}
/**
*
* #return
* The from
*/
public Integer getFrom() {
return from;
}
/**
*
* #param from
* The from
*/
public void setFrom(Integer from) {
this.from = from;
}
/**
*
* #return
* The to
*/
public Integer getTo() {
return to;
}
/**
*
* #param to
* The to
*/
public void setTo(Integer to) {
this.to = to;
}
}
I tested this (I am using Google GSON library), and I was able to successfully read it.

Basically, there are two JSON arrays but you are accessing only one arrays that is why that error is shown
try {
JSONArray jsonArray = new JSONArray(a);
for (int j=0;j<jsonArray.length();j++) {
JSONArray timeJSONArray = jsonArray.getJSONArray(j);
for(int i = 0; i < timeJSONArray.length(); i++){
int daysByte = timeJSONArray.getJSONObject(i).getInt("daysByte");
int from = timeJSONArray.getJSONObject(i).getInt("from");
int to = timeJSONArray.getJSONObject(i).getInt("to");
System.out.println("TO " + to);
}
}
} catch (JSONException e) {
e.printStackTrace();
}

After 1 hour of debugging your Json array I finally managed to figure out your actual issue. Its not only a Json Array its array inside the array.
So loop like this,
for (int i = 0; i < timeJSONArray.length(); i++) {
for(int j= 0;j<i;j++) {
int daysByte = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("daysByte");
int from = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("from");
int to = timeJSONArray.getJSONArray(i).getJSONObject(j).getInt("to");
Log.d("dataRecieved", "daybyte " + daysByte + "from " + from + "to " + to);
}
}
And do others as you need.

Related

Why is it saying that I am getting nothing wrong?

In this program, I am supposed to return how many questions I got right and wrong. But regardless of what I put down, it'll say that I got 20 questions correct, and 0 wrong. Anyone know how to fix this so it'll be more accurate than that?
Class:
public class KNW_DriverExam
{
//Create the arrays/Declare variable
//Intialize theAnswers array
private String[] theAnswers = {"B" , "D" , "A" , "A" , "C" ,
"A" , "B" , "A" , "C" , "D" ,
"B" , "C" , "D" , "A" , "D" ,
"C" , "C" , "B" , "D" , "A" };
private String[] userAnswers;
int[] missed = new int [theAnswers.length];
/**The DriverExam method, recieves answers
* #param Answer, the answer
* */
public KNW_DriverExam(String[] Answer)
{
userAnswers = new String[theAnswers.length];
for(int i = 0; i < theAnswers.length; i++)
{
userAnswers[i] = theAnswers[i];
}
}
/**The passed method, see if user passes or fails
* #return true if user passed
* #return false if user failed
* */
public boolean passed()
{
if(totalCorrect()>=15)
{
return true;
}
else
{
return false;
}
}
/**The totalCorrect method, see how many user got right
* #return correctCount, how many the user got right
* */
public int totalCorrect()
{
int correctCount = 0;
for(int i = 0; i < theAnswers.length; i++)
{
if(userAnswers[i].equalsIgnoreCase(theAnswers[i]))
{
correctCount++;
}
}
return correctCount;
}
/**The totalIncorrect method, how many the user got wrong
* #return incorrectCount, how many the user got wrong
* */
public int totalIncorrect()
{
int incorrectCount = 0;
for(int i = 0; i < theAnswers.length; i++)
{
if(!(userAnswers[i].equalsIgnoreCase(theAnswers[i])))
{
missed[incorrectCount] = i;
incorrectCount++;
}
}
return incorrectCount;
}
/**The missedQuestions method, how many quetions user missed.
* #return missed, missed questions
* */
public int[] questionsMissed()
{
return missed;
}
}
Demo:
import java.util.Scanner;
public class KNW_DriverExamDemo
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Driver's Exam/n");
System.out.println("20 Multiple Choice Questions Mark A,B,C,D");
//Inputting string
String[] answers = new String[20];
String answer;
for(int i = 0; i < 20; i++)
{
do
{
System.out.println((i + 1) + ": ");
answer = input.nextLine();
}
while(!isValidAnswer(answer));
{
answers[i] = answer;
}
}
KNW_DriverExam exam = new KNW_DriverExam(answers);
System.out.println("Results\n\n");
System.out.println("Total Correct: " + exam.totalCorrect() + "\n");
System.out.println("Total Incorrect: " + exam.totalIncorrect() + "\n");
if(exam.totalIncorrect() > 0)
{
System.out.println("The Incorrect Answers Are: ");
int missedIndex;
for(int i = 0; i < exam.totalIncorrect(); i++)
{
missedIndex = exam.questionsMissed()[i] + 1;
System.out.println(" " + missedIndex);
}
}
}
public static boolean isValidAnswer(String answer)
{
return "A".equalsIgnoreCase(answer) ||
"B".equalsIgnoreCase(answer) ||
"C".equalsIgnoreCase(answer) ||
"D".equalsIgnoreCase(answer);
}
}
Take a look at your constructor. When you're assigning to userAnswers you're using theAnswers and not the supplied Answer.
public KNW_DriverExam(String[] Answer) {
userAnswers = new String[Answers.length];
for(int i = 0; i < Answers.length; i++) {
userAnswers[i] = Answers[i];
}
}

How to load All Arraylist from the model function?

I'm using lib FlexibleAdapter to load JSON API in android studio like this.
public void createHolderSectionsDatabase(int size, int headers) {
databaseType = DatabaseType.MODEL_HOLDERS;
HeaderHolder header = null;
mItems.clear();
int lastHeaderId = 0;
for (int i = 0; i < size; i++) {
header = i % Math.round(size / headers) == 0 ? newHeaderHolder(++lastHeaderId) : header;
mItems.add(newItemHolder(i + 1, header));
}
}
private HeaderHolder newHeaderHolder(int i) {
HeaderModel model = new HeaderModel("H" + i);
model.setTitle("Header " + i);
return new HeaderHolder(model);
}
private ItemHolder newItemHolder(int i, HeaderHolder header) {
ItemModel model = new ItemModel("I" + i);
model.setTitle("Holder Item " + i);
model.setSubtitle("Subtitle " + i);
return new ItemHolder(model, header);
}
Above code only loads the data from looping model item.
I could apply with JSON API such as:
How to change code like:
/* for (int i = 0; i < size; i++) {
header = i % Math.round(size / headers) == 0 ? newHeaderHolder(++lastHeaderId) : header;
mItems.add(newItemHolder(i + 1, header));
}*/
Like this:
listArrayFromJSON = getArrayJSON(); //get JSON with GSON request
mItems.addAll(ListArrayFromJSON,header); //not add`
I dont know your json string structure but, you can update question or inspire from below
public class DataHolder{
private ArrayList<ItemHolder> items; //json object name
private ArrayList<HeaderHolder> headers; //json object name
public Arraylist<ItemHolder> getItems(){
return items;
}
public Arraylist<HeaderHolder> getHeaders(){
return items;
}
}
DataHolder holder = new Gson().fromJson(jsonString, DataHolder.class);
mItems.addAll(holder.getItems());
mHeaders.addAll(holder.getHeaders());

Get JSON String by iterating over array inside an object

Im working on an app where Im parsing JSON file and get the strings from it, but there is one String I have no idea why cant I get it into my activity.
the String is Object > Array > String
I have 2 activities and 1 model.
MainActivity: where Im parsing the JSON.
DetailActivity: where I need the String.
PostModel: a model where I have all setter and getter.
JSON:
{
"status":"ok",
"count":10,
"count_total":184,
"pages":19,
"posts":[
{ },
{
"id":2413,
,
"categories":[
{
"id":100,
"slug":"logging",
"title":"logging",
"description":"",
"parent":0,
"post_count":1
}
],
"comments":[
{
"id":3564,
"content":"<p>\u47 <\/p>\n",
"parent":0
}
],
"comment_count":1,
"thumbnail":"http:\/\/www.5.com\/wtent\g",
"custom_fields":{
"dsq_thread_id":[
"2365140"
],
"videoID":[
"--ffwf92jvDFy"
]
},
"thumbnail_images":{
"full":{
"url":"http:\/\/www.5.com\/jpg",
"width":727,
"height":454
},
"thumbnail":{
"url":"http:\/\/www.5.com\/wp-con50.jpg",
"width":150,
"height":150
}
}
}
]
}
PostModel:
private List<VidCast> videoIDList;
private String videoID;
public String getVideoID() {
return videoID;
}
public void setVideoID(String videoID) {
this.videoID = videoID;
}
public List<VidCast> getvideoIDList() { return videoIDList; }
public void setvideoIDList(List<VidCast> videoIDList) {
this.videoIDList = videoIDList;
}
public static class VidCast {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
MainActivity:
List<PostModel.VidCast> vidCasts = JsonPath.parse(URL_TO_HIT).read("$.posts.[*].custom_fields.[*].videoID[*]");
vidCasts = new ArrayList<>();
for (int s = 0 ; s < finalObject.getJSONArray("custom_fields").length() ; s++){
PostModel.VidCast vidCast = new PostModel.VidCast();
vidCast.setName(videoID);
vidCasts.add(vidCast);
}
postModel.setvideoIDList(vidCasts);
// adding the final object in the list
postModelList.add(postModel);
}
return postModelList;
}
}
DetailActivity:
StringBuffer stringBuffer = new StringBuffer();
for(PostModel.CategoryCast categoryCast : postModel.getCategoryCastList()){
stringBuffer.append(categoryCast.getName() + ", ");
}
StringBuffer videoStringBuffer = new StringBuffer();
for(PostModel.VidCast videoIDList : postModel.getvideoIDList()) {
videoStringBuffer.append(videoStringBuffer.toString());
}
At the last file is where I need to get the <> String. I spent a lot of time I just cant figure it out how I can iterate over array inside an object.
Thanks in advance!
__________update________
I managed to parse it that way :
JSONObject customFields = finalObject.getJSONObject("custom_fields");
JSONArray vidCastsJson = customFields.getJSONArray("videoID");
List<PostModel.VidCast> videoIds = new ArrayList<>();
for (int s = 0 ; s < vidCastsJson.length() ; s++){
PostModel.VidCast vidCast = new PostModel.VidCast();
vidCast.setName(vidCastsJson.optString(s));
videoIds.add(vidCast);
String videoID = String.valueOf(vidCastsJson);
vidCast.setName(videoID);
and I use Stringbuffer at DetailActivityStringBuffer
videoStringBuffer = new StringBuffer();
for(PostModel.VidCast vidCast : postModel.getvideoIDList()) {
videoStringBuffer.append(vidCast.getName());
String videoID = vidCast.toString();
}
But now I'm getting the videoID with the array brackets like that ["F3lyzrt"] I want it as a string to be only F3lyzrt, so I can pass it to my youtube player. Any advice will be appropriated.
Thanks,
It would look something like this:
JSONObject root = // however you get your root JSON object
JSONArray posts = root.optJSONArray("posts");
for(int i=0; i < posts.length(); i++){
JSONObject post = posts.optJSONObject(i);
int id = post.optInt("id");
JSONArray categories = post.optJSONArray("categories");
// etc.
}
Though you might want to consider using GSON or Jackson. With those libraries you can define a model to represent the data (jsonschema2pojo.org can help with that) and then it does all the parsing for you.
EDIT
You're not even trying to get the video id. Here's your code:
for (int s = 0; s < finalObject.getJSONArray("videoID").length(); s++){
{
postModel.setVideoID(videoID);
postModelList.add(postModel);
}
You see how you're not retrieving the contents of the json array?
JSONArray videoIds = finalObject.getJSONArray("videoID");
for (int s = 0; s < videoIds.length(); s++){
String videoID = videoIds.optString(s);
postModel.setVideoID(videoID);
postModelList.add(postModel);
}

Null pointer exception, taking data form lists and arrays

I've checked everything several time, can't get where I am wrong..
Main class:
try
{
File productData = new File("productData.txt");
Product [] consideredRange = InputFileData
.readProductDataFile(productData);
ElectronicsEquipmentSupplier management =
new ElectronicsEquipmentSupplier(1, 12, consideredRange);
File customerData = new File("CustomerData.txt");
Scanner fileScan = new Scanner(customerData);
while(fileScan.hasNext())
management.addNewCustomer(InputFileData.
readCustomerData(fileScan));
management.addNewPurchaseOrder("21/01/12", "PSC-1235", "kD/9767", 50);
}
catch(Exception e)
{
System.out.println(e);
e.printStackTrace();
}
InputFileData class works perfectly. I have created an object of ElectronicsEquipmentSupplier with a consideredRange of products. Also added customers to a customersList.
Here is ElectronicsEquipmentSupplier class:
public class ElectronicsEquipmentSupplier
{
private int currentMonth;
private int currentYear;
private Product [] productRange;
private CustomerDetailsList customersList;
private PurchaseOrderList currentYearList;
private PurchaseOrderList lastYearList;
public ElectronicsEquipmentSupplier(int currentMonth, int currentYear, Product [] range)
{
this.currentMonth = currentMonth;
this.currentYear = currentYear;
productRange = new Product[range.length];
customersList = new CustomerDetailsList();
currentYearList = new PurchaseOrderList();
lastYearList = new PurchaseOrderList();
}
public void addNewPurchaseOrder(String dateStr, String customerID,
String productCode, int qty) throws IncorrectPurchaseOrderException
{
// check for positive order quantity
if(qty < 1)
throw new IncorrectPurchaseOrderException("Order quantity must be"
+ " positive!");
// check for the product code in given range and get that product
Product foundProduct = null;
for(int i = 0; i < productRange.length; i++)
{
if(productRange[i].getProductCode().equals(productCode))
{
foundProduct = productRange[i];
break;
}
}
if(foundProduct == null)
throw new IncorrectPurchaseOrderException("Product code is not in"
+ " the product range!");
try
{
// creating OrderDate object and getting appropriate discount
OrderDate newDate = new OrderDate(dateStr);
int discount = customersList.findCustomer(customerID).
getDiscountRate();
// creating purchase order and adding it to a list
PurchaseOrder givenOrder = new PurchaseOrder(newDate, customerID,
foundProduct, qty, discount);
currentYearList.addPurchaseOrder(givenOrder);
// updating the record of purchasing customer
int priceValue = givenOrder.getFullPriceValue();
customersList.findCustomer(customerID)
.updateTotalOrdersValue(priceValue);
}
catch(Exception e)
{
throw new IncorrectPurchaseOrderException("The problem is with: "
+ "\n" + e);
}
}
It shows that I've got NullPointerException at: if(productRange[i].getProductCode().equals(productCode))
and in the main class at:
management.addNewPurchaseOrder("21/01/12", "PSC-1235", "kD/9767", 50);
Can't get why, as I have all required info..
Thank you!
Update 1:
Added this to the main method to solve first issue:
for(int i = 0; i < consideredRange.length; i++)
management.getProductRange()[i] = consideredRange[i];
But now the ID of a customer cannot be found...
That's the method in CustomerDetailsList class, which throws exception:
public CustomerDetails findCustomer(String givenID)
throws CustomerNotFoundException
{
int i = 0;
boolean match = false;
while(!match && i < listOfCustomerDetails.size())
{
match = listOfCustomerDetails.get(i).getCustomerID()
.equals(givenID);
i++;
}
if(!match)
throw new CustomerNotFoundException("The provided ID has not been"
+ " found");
else
return listOfCustomerDetails.get(i);
}
Update 2: updated .findCustomer() as SMA suggested
You are trying to initialize product in constructor like
productRange = new Product[range.length];
And then using it like:
if(productRange[i].getProductCode().equals(productCode))
Now you allocated space for your array but individual array elements i.e. products are not initialized and hence you get NullPointerException. To resolve the issue, you could do something like:
productRange[i] = new Product(..);//and then use it
Most likely because productRange[i] has not been initialized.
In your constructor you need to fully initialise the productRange array. Right now you are just creating an array of null references.
public ElectronicsEquipmentSupplier(int currentMonth,
int currentYear,
Product [] range) {
this.currentMonth = currentMonth;
this.currentYear = currentYear;
productRange = new Product[range.length];
for (int i = 0; i < productRange.length; i++) {
productRange[i] = range[i];
}
customersList = new CustomerDetailsList();
currentYearList = new PurchaseOrderList();
lastYearList = new PurchaseOrderList();
}
The above solution build a new array which reference the same objects as the range array passed to the constructor.
You may just want to reference the array without any allocation, e.g.
public ElectronicsEquipmentSupplier(int currentMonth,
int currentYear,
Product [] range) {
//...
productRange = range;
//...
}
Or do a deep copy of the range array, assuming you have either a Product#clone() method or a Product constructor that takes a Product parameter, e.g.
public ElectronicsEquipmentSupplier(int currentMonth,
int currentYear,
Product [] range) {
//...
productRange = new Product[range.length];
for (int i = 0; i < productRange.length; i++) {
productRange[i] = new Product(range[i]);
}
//...
}
The choice between these different methods depends on how the ElectronicsEquipmentSupplier class is used.

Parse the JSON String efficiently and in a clean way

In my below code, colData stores JSON String. Sample example for colData-
{"lv":[{"v":{"price":70.0,"userId":419},"cn":3},
{"v":{"price":149.99,"userId":419},"cn":3},
{"v":{"price":54.95,"userId":419},"cn":3}],
"lmd":20130206212543}
Now I am trying to match id value with userId value in the above JSON String. I am getting id value from a different source.
Meaning if id value is 419 then in the above JSON String userId value should also be 419. And in the JSON String, it might be possible there are lot of userId values so all the userId values should be matching with id. If any of them doesn't matches then log the exception.
So I was trying something like this-
final int id = generateRandomId(random);
for (String str : colData) {
if (!isJSONValid(str, id)) {
// log the exception here
LOG.error("Invalid JSON String " +str+ "with id" +id);
}
}
public boolean isJSONValid(final String str, final int id) {
boolean valid = false;
try {
final JSONObject obj = new JSONObject(str);
final JSONArray geodata = obj.getJSONArray("lv");
final int n = geodata.length();
for (int i = 0; i < n; ++i) {
final JSONObject person = geodata.getJSONObject(i);
JSONObject menu = person.getJSONObject("v");
if(menu.getInt("userId") == id) {
valid = true;
}
}
} catch (JSONException ex) {
valid = false;
}
return valid;
}
As per my understanding it looks like I can make isJSONValid method more cleaner. In my above isJSONValid method as I am repeating some stuff which I shouldn't be doing. Can anyone help me out how to make this more cleaner if I have missed anything. I will be able to learn some more stuff. Thanks for the help
You can initialize valid = true and set it to false when you find a non-valid userId and immediately fail:
public boolean isJSONValid(final String str, final int id) {
boolean valid = true;
try {
final JSONObject obj = new JSONObject(str);
final JSONArray geodata = obj.getJSONArray("lv");
final int n = geodata.length();
for (int i = 0; i < n; ++i) {
final JSONObject person = geodata.getJSONObject(i);
JSONObject menu = person.getJSONObject("v");
if(menu.getInt("userId") != id) {
valid = false;
break;
}
}
} catch (JSONException ex) {
valid = false;
}
return valid;
}
This way you iterate through all array's elements only if all are valid, which is the only case you actually have to.

Categories