My question was like this: https://stackoverflow.com/questions/20919343/php-getting-count-of-how-many-x-and-y-in-a-row-then-getting-other-data-of-x-and
But then i thought about doing the job from Android Part. So i have 2 JSONObjects which generated from php. First object has "value" and "total" arrays. Second one has "name", "surname" and "number" and a few more arrays. Now i need to compare number from second JSONObject and value from first. I tried some loops, but it creates double as expected. Here is my onPostExecute method:
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pDialog.dismiss();
try {
JSONObject jsonObj = new JSONObject(jsonStr);
JSONObject jsonObj2 = new JSONObject(jsonStr);
// Getting JSON Array node
sonuc = jsonObj.getJSONArray(TAG_BASLIK);
// looping through All Contacts
for (int i = 0; i < sonuc.length(); i++) {
JSONObject c = sonuc.getJSONObject(i);
AdayNumara = c.getString(TAG_OY);
ToplamOy = c.getString(TAG_TOPLAM);
Log.i("Aday Numaraları", AdayNumara);
Log.i("Oy Sayısı", ToplamOy);
pie.addItem(AdayNumara,Float.valueOf(ToplamOy), pRenk.get(i));
adaylar = jsonObj2.getJSONArray(TAG_ADAYLAR);
for(int j=0; j< adaylar.length(); j++){
JSONObject c2 = adaylar.getJSONObject(j);
String no = c2.getString(TAG_NO);
String ad = c2.getString(TAG_AD);
String soyad = c2.getString(TAG_SOYAD);
String resim = c2.getString(TAG_RESIM);
HashMap<String, String> aday = new HashMap<String, String>();
do{
aday.put(TAG_AD, ad);
aday.put(TAG_SOYAD, soyad);
aday.put(TAG_RESIM, resim);
aday.put(TAG_NO, no);
aday.put(TAG_TOPLAM, ToplamOy);
adayList.add(aday);} while(AdayNumara == no);
}
adapter=new LazyAdapter2(SecimSonuclari.this, adayList);
lv.setAdapter(adapter);
}
}catch (JSONException e) {
e.printStackTrace();
}
}
Code is probably has wrong approachs since I'm new to Android.
What I am getting now is for value in listview. There must be 2. The first two has same value like 1 and 1 on their number line. The second couple has the other number, lets say 2.
I found my problem. It appears to using "==" is wrong.
if(AdayNumara.equals(no)){
aday.put(TAG_AD, ad);
aday.put(TAG_SOYAD, soyad);
aday.put(TAG_RESIM, resim);
aday.put(TAG_NO, no);
aday.put(TAG_TOPLAM, ToplamOy);
adayList.add(aday);
}
I know this question in a year old, but anyway...
I needed to compare two JSONObject values without internal JSONObject/JSONArray. Most SO solutions recommend a 3-rd party java library, which would be a bit too heavy.
First of all, the Android's built-in JSONObject does not define hashCode() and equals() in any sensible way. I used a wrapper class with a JSONObject inside.
The below functions are placed in some utility class, it is a trivial exercise to use them to define hashCode() and equals().
public static int jsonHashCode(JSONObject j) {
if (j == null) {
return 0;
}
int res = 0;
for (String s : new AsIterable<String>(j.keys())) {
res += s.hashCode();
}
return res;
}
public static boolean comparesEqual(JSONObject x, JSONObject y, Collection<String>only, Collection<String>except) {
Set<String> keys = keySet(x);
keys.addAll(keySet(y));
if (only != null) {
keys.retainAll(only);
}
if (except != null) {
keys.removeAll(except);
}
for (String s : keys) {
Object a = null, b = null;
try {
a = x.get(s);
} catch (JSONException e) {
}
try {
b = x.get(s);
} catch (JSONException e) {
}
if (a != null) {
if (!a.equals(b)) {
return false;
}
} else if (b != null) {
if (!b.equals(a)) {
return false;
}
}
}
return true;
}
public static Set<String> keySet(JSONObject j) {
Set<String> res = new TreeSet<String>();
for (String s : new AsIterable<String>(j.keys())) {
res.add(s);
}
return res;
}
where AsIterable lets us use the for(:) loop with an iterator and is defined as:
public class AsIterable<T> implements Iterable<T> {
private Iterator<T> iterator;
public AsIterable(Iterator<T> iterator) {
this.iterator = iterator;
}
public Iterator<T> iterator() {
return iterator;
}
}
You are welcome to write and post the recursive version of this code, supporting JSONObject/JSONArray values.
For my use case, I ended up iterating over the keys of the first json object and checked to see if the value matched what was in the second json object.
JSONObject obj = new JSONObject("some json string");
JSONObject comparison = new JSONObject("some other json string with the same data but different key order");
boolean equal = true;
for (Iterator<String> iterator = obj.keys(); iterator.hasNext(); ) {
String curKey = iterator.next();
if(!obj.getString(curKey).equals(comparison.getString(curKey))){
equal = false;
break;
}
}
if(equal){
// do the thing that i want to do if the two objs are equal
}
Related
I'm using Google Cloud Firestore API for a project that involves simple retrieval of data from the server database. Having set up everything I can't seem to figure out how to properly parse the returned JSON, as all of my attempts have been unsuccessful.
Using the Firestore package is out of question as this is a defined project.
I have tried the classic approach since Android studio only gets the field part with its HTTPURLConnection.
This is the JSON structure:
{
"documents": [
{
"name": "projects/...",
"fields": {
"name": {
"stringValue": "Q1"
},
"myValues": {
"arrayValue": {
"values": [
{
"stringValue": "First"
}
]
}
},
"index": {
"integerValue": "0"
}
},
"createTime": "2019-05-24T10:07:10.864421Z",
"updateTime": "2019-05-28T07:52:34.445600Z"
}
]
}
Here's my attempt at parsing it:
public ArrayList<Question> parse(String json)
{
ArrayList<Question> list = new ArrayList<Question>();
try {
int indeks=0;
String qName="";
ArrayList<String> answerList= new ArrayList<String>();
JSONObject object = new JSONObject(json);
JSONArray dokumenti = object.getJSONArray("documents");
for (int j = 0; j < dokumenti.length(); j++) {
JSONObject jObject = dokumenti.getJSONObject(j);
if (jObject.has("index")) indeks = jObject.getInt("index");
if (jObject.has("name")) qName= jObject.getString("name");
JSONArray answerArray= jObject.getJSONArray("myValues");
for (int i = 0; i < answerArray.length(); i++) {
try {
String answer= answerArray.getString(i);
answerList.add(answer);
} catch (JSONException e) {
Log.d("OOPS", qName);
}
}
}
list.add(new Question(qName, qName, answerList, answerList.get(indeks), 0));
}
catch(JSONException e)
{
//something
}
return list;
}
Database structure
I expect that all of the documents get parsed and added to the list ArrayList but it seems like nothing happens and I can't find the TAG in the Logcat.
It looks you're trying to get index before accessing its parent fields.
if (jObject.has("index")) indeks = jObject.getInt("index");
In this line you should have gotten before the parent object fields, otherwise you will not have access to index or name.
EDIT
I've been checking your code and you are parsing some things wrong.
Let's go step by step:
You are trying to access to the childs of fields without accessing to their parent.
The solution following your structure would be something like this:
JSONObject jObject = dokumenti.getJSONObject(j);
JSONObject fields = jObject.getJSONObject("fields");
if (fields.has("index") && fields.getJSONObject("index").has("integerValue")) {
indeks = fields.getJSONObject("index").getInt("integerValue");
}
if (fields.has("name") && fields.getJSONObject("name").has("stringValue")) {
qName = fields.getJSONObject("name").getString("stringValue");
}
You're trying to access also the myValues array not respecting the objects hierarchy. The correct way should be something like this:
JSONArray answerArray = fields.getJSONObject("myValues").getJSONObject("arrayValue").getJSONArray("values");
for (int i = 0; i < answerArray.length(); i++) {
try {
String answer = answerArray.getJSONObject(i).getString("stringValue");
answerList.add(answer);
} catch (JSONException e) {
Log.d("OOPS", qName);
}
}
With this changes I have been able to parse the Json you posted without any problem. Here you can find the complete code:
public ArrayList<Question> parse(String json)
{
ArrayList<Question> list = new ArrayList<Question>();
try {
int indeks = 0;
String qName = "";
ArrayList<String> answerList = new ArrayList<String>();
JSONObject object = new JSONObject(json);
JSONArray dokumenti = object.getJSONArray("documents");
for (int j = 0; j < dokumenti.length(); j++) {
JSONObject jObject = dokumenti.getJSONObject(j);
JSONObject fields = jObject.getJSONObject("fields");
if (fields.has("index") && fields.getJSONObject("index").has("integerValue")) {
indeks = fields.getJSONObject("index").getInt("integerValue");
}
if (fields.has("name") && fields.getJSONObject("name").has("stringValue")) {
qName = fields.getJSONObject("name").getString("stringValue");
}
JSONArray answerArray = fields.getJSONObject("myValues").getJSONObject("arrayValue").getJSONArray("values");
for (int i = 0; i < answerArray.length(); i++) {
try {
String answer= answerArray.getString(i);
answerList.add(answer);
} catch (JSONException e) {
Log.d("OOPS", qName);
}
}
}
list.add(new Question(qName, qName, answerList, answerList.get(indeks), 0));
}
catch(JSONException e)
{
//something
}
return list;
}
JavaScript example:
function toValue(field) {
return "integerValue" in field
? Number(field.integerValue)
: "doubleValue" in field
? Number(field.doubleValue)
: "arrayValue" in field
? field.arrayValue.values.map(toValue)
: "mapValue" in field
? toJSON(field.mapValue)
: Object.entries(field)[0][1];
}
function toJSON(doc) {
return Object.fromEntries(
Object.entries(doc.fields ?? {}).map(([key, field]) => [key, toValue(field)])
);
}
I have a JSON that contains the names of Countries, their states and cities of those states. Here is the json.
I am able to get all the countries but I can't figure out how to get the states based on the selected country and then cities based on the selected state.
Here is how I got the countries.enter code here
First to load the file from assets:
public String loadJSONFromAsset() {
String json = null;
try {
InputStream is = getAssets().open("Contries.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
Then to load the countries into an ArrayList.
public void loadCountries(String parent, String child, ArrayList<String> listValue)
{
try {
JSONObject obj = new JSONObject(loadJSONFromAsset());
JSONArray m_jArry = obj.getJSONArray(parent);;
ArrayList<HashMap<String, String>> formList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> m_li;
// listValue = new ArrayList<>();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
listValue.add(jo_inside.getString(child));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Then this line finally:
loadCountries("Countries", "CountryName", countries);
After I have selected a country, I want to load its states. maybe something like this:
loadCountries("Pakistan", "StateName", states);
and then:
loadCountries("Islamabad Capital Territory", "CityName", cities);
Any help is greatly appreciated.
Working with JSON can be error-prone. Why don't we model objects around your data and we can do something a little more clearer.
Overview.
Lets' Model your objects
Let's Deserialize your raw json into "Objects"
Then we can "query" our modelled objects!
Step 1 - Modelling.
Note I'm not including constructors, getters, setters and any other boiler plate.
public class Country {
private List<State> states;
private String name;
public Optional<State> getStateByName(String name) {
return States.stream().filter(state -> state.getName().equals(name)).findFirst();
}
}
public class State {
private List<String> cities;
private String name;
public Optional<String> getCityByName(String name) {
return cities.stream().filter(city -> city.equals(name)).findFirst();
}
}
public class CountryDataProvider {
private List<Country> countries;
public CountryDataProvider(String rawData) {
// parse your json to create a List of object Country (tip: Use something like Jackson or Gson to do this for you).
// Ref to part 2
}
public Optional<Country> getCountryByName(String name) {
return countries.stream().filter(country -> country.getName().equals(name)).findFirst();
}
}
Step 2 - Deserialize.
This is a broad topic and To be honest there is a lot of libraries that will do it better and they are really easy to add to your project. Here are a few:
Jackson https://github.com/FasterXML/jackson
GSON https://github.com/google/gson <- My pick.
Step 3 - Query
From here you can do what ever you want
countryData = new CountryDataProvider(data);
Optional<List<String>> countriesInPunjab = countryData.getCountryByName("Pakistan")
.map(country -> country.getStateByName("Punjab")
.map(state -> state.getCities()); // would give you all the cities in Punjab, Pakistan.
The code I have given in my example does use functional and Optional interfaces (in Java 8). Let me know if you want them rewritten in a less functional way.
Here is another solution, not very CPU friendly but it works:
First use this method to get a list of countries:
public void loadCountries(String parent, String child, ArrayList<String> listValue)
{
try {
JSONObject obj = new JSONObject(loadJSONFromAsset());
JSONArray m_jArry = obj.getJSONArray(parent);
// m_jArry;
ArrayList<HashMap<String, String>> formList = new ArrayList<HashMap<String, String>>();
HashMap<String, String> m_li;
// listValue = new ArrayList<>();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
listValue.add(jo_inside.getString(child));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Call this method like this:
loadCountries("Countries", "CountryName", countries);
Then use the following method to load the States and Cities.
private void getCitiesByState(String countryName, String stateName)
{
try {
JSONObject json = new JSONObject(loadJSONFromAsset());
JSONArray countriesArray = json.getJSONArray("Countries");
for(int i = 0; i < countriesArray.length(); i++)
{
JSONObject countryJSON = countriesArray.getJSONObject(i);
if(countryJSON.getString("CountryName").equals(countryName))
{
JSONArray statesArray = countryJSON.getJSONArray("States");
states.clear();
for(int j = 0; j < statesArray.length(); j++)
{
JSONObject statesJSON = statesArray.getJSONObject(j);
states.add(statesJSON.getString("StateName"));
if(statesJSON.getString("StateName").equals(stateName))
{
JSONArray citiesarray = statesJSON.getJSONArray("Cities");
cities.clear();
for(int k = 0; k < citiesarray.length(); k++)
{
cities.add(citiesarray.getString(k));
}
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
I am trying to order my JSON data by name, I've found some answers here, but nothing works for my case. I have tried to update my code as you see below. I marked there what I have removed from original code, and what have I added:
#Override
protected Boolean doInBackground(String... args) {
HttpHandler sh = new HttpHandler();
String url = "androidnews.json";
String jsonStr = sh.makeServiceCall(url);
if (jsonStr != null) {
try {
//removed this:
//JSONObject jsonObj = new JSONObject(jsonStr);
//JSONArray actors = jsonObj.getJSONArray("result");
//ADDED:
ArrayList<JSONObject> array = new ArrayList<JSONObject>();
JSONArray actors = new JSONArray("result");
for (int i = 0; i < actors.length(); i++) {
JSONObject c = actors.getJSONObject(i);
//ADDED:
array.add(actors.getJSONObject(i));
Actors actor = new Actors();
actor.setName(c.getString("name"));
actor.setThumb(c.getString("thumb"));
actorsList.add(actor);
}
//ADDED:
Collections.sort(array, new Comparator<JSONObject>() {
#Override
public int compare(JSONObject lhs, JSONObject rhs) {
// TODO Auto-generated method stub
try {
return (lhs.getString("name").toLowerCase().compareTo(rhs.getString("name").toLowerCase()));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 0;
}
}
});
} catch (final JSONException e) {
Zoznam.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Zoznam.this.getApplicationContext(),
"Data error " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}); }
return true;
} else {
Zoznam.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(Zoznam.this.getApplicationContext(),
"Chyba internetového pripojenia.",
Toast.LENGTH_LONG).show();
}
});
return false;
}
}
But after I test it, I have this error: Value result of type java.lang.String cannot be converted to JSONArray
My JSON begins with: {"result": [{"name": "Joe","thumb": "image.jpg",...
Instead of sorting your JSONArray try sorting your Arraylist with custom object and use it. you can do something like this
Collections.sort(actorsList, new Comparator<Actors>() {
#Override
public int compare(Actors lhs, Actors rhs) {
return lhs.getName().compareTo(rhs.getName());
}
});
A solution to your current problem:
Im guessing that you are using the org.json library.
Currently you are trying to create a JSONArray from the string "result".
This is how you access an array within the JSON file:
JSONObject obj = new JSONObject(Files.readAllLines(Paths.get("/path/to/your/file.json")));
JSONArray arr = obj.getJSONArray("number");
Source: more helpful examples like the one above
Further information:
As it seems like your not to familiar with the org.json approach I would highly recommend taking a look at gson as it provides an easy way to map JSON entries to objects (or even Arrays of an Object).
See: this and this
Here's the json I currently use in my code :
{"forceDeviceLockout":0,"canStartValue":true,"destructOnRead":[30,60,300]}
I use the following function to get the json values:
private Object getValueForField(Field field) {
if (runtimeConfiguration.has(field.fieldName) && field.updateFromServer) {
try {
Object value = runtimeConfiguration.get(field.fieldName);
if (value instanceof JSONArray) {
JSONArray values = (JSONArray) value;
if (values.get(0) instanceof Number) {
long[] retVals = new long[values.length()];
for (int i = 0; i < values.length(); i++) {
retVals[i] = ((Number) values.get(i)).longValue();
}
return retVals;
}
} else if (value instanceof Number) {
return ((Number) value).longValue();
} else {
return value;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return field.defaultValue;
}
Now, I have a new nested json as follows:
{"forceDeviceLockout":0,"canStartValue":true,"destructOnRead":[30,60,300],"NEWVALUE":{"canStartNewValue1":true,"canStartroupValue":true}
In the new json I am adding the nested json object : NEWVALUE which has 2 objects within itself.
I am a little weak at json so unsure how to go about modifying my code to retrieve the above individual values. Any ideas?
I don't know why are you making it so complicated! but see this code I wrote for you. it might give you an idea:
public void printFieldsValues(Object object){
try{
Field[] fields = object.getClass().getFields();
JSONObject jsonObject = new JSONObject();
for(Field field : fields){
jsonObject.put(field.getName(), field.get(object));
}
JSONObject newValue = new JSONObject("{\"canStartNewValue1\":true,"
+ "\"canStartroupValue\":true}");
jsonObject.put("NEWVALUE", newValue);
printJson(jsonObject);
}catch(Exception e){
e.printStackTrace();
}
}
public void printJson(JSONObject jsonObject) throws JSONException{
Iterator<String> keys = jsonObject.keys();
String key;
while(keys.hasNext()){
key = keys.next();
try{
printJson(new JSONObject(jsonObject.getString(key)));
}catch(Exception e){
Log.d("TAG", "key = " + key);
Log.d("TAG", "value = " + jsonObject.get(key).toString());
}
}
}
and in your main Object you can call it like this:
printFieldsValues(this);
If those json keys are predefined we can access them like this
public class SampleModel {
public int forceDeviceLockout;
public boolean canStartValue;
public int[] destructOnRead;
public NestedModel NEWVALUE;
}
public class NestedModel {
public boolean canStartNewValue1;
public boolean canStartroupValue;
}
Gson gson = new Gson();
SampleModel sampleModel = gson.fromJson("{\"forceDeviceLockout\":0,\"canStartValue\":true,\"destructOnRead\":[30,60,300],\"NEWVALUE\":{\"canStartNewValue1\":true,\"canStartroupValue\":true}}",SampleModel.class);
Log.d("canStartNewValue : " ,sampleModel.canStartNewValue)
Log.d("canStartNewValue1 : " , sampleModel.NEWVALUE.canStartNewValue1);
Note : Need to add dependency compile 'com.google.code.gson:gson:2.8.2'
If you just want to modify your current code to parse the json received you could just add
if(value instance of JSONObject){
JSONObject jsonObject = (JSONObject) value;
return jsonObject;
}
I have a problem with json.
I get this response from server:
{"TESTS":true,"TESTS_VIEW":true,"ORDER":true,"PARAMETERS":true,"VIEW":true}
How can I save this data in array or something else to have schema: key - value?
Hmm, not sure I understand why you want this. A JSONObject gives you exactly that, have a look at JSONObject.get():
JSONObject json = new JSONObject(yourjsonstringfromserver);
boolean tests = json.getBoolean("TESTS");
Still, if you want to iterate over all values you can do like this:
Map<String, Object> map = new HashMap<String, Object>();
Iterator<String> keys = json.keys();
for(String key : keys) {
try {
Object value = json.get(key);
map.put(key, value);
}
catch (JSONException e) {
// Something went wrong!
}
}
JSONObject object = YourObjectHere;
Map<String,Boolean> dict = new HashMap<String,Boolean>();
Iterator it = object.keyes();
while( it.hasNext() ){
String key = it.next();
String value = object.get(key);
dict.put( key, value );
}
Solution, more or less. //Written without checking in IDE so may contain bugs/errors
JSONObject json = new JSONObject(response);
json.getInt(keyA);
json.getString(keyB);
and etc;
You can using this function with httpResponse is your json string:
public static YourModel parseJson(String httpResponse) {
YourModel objObject = new YourModel();
try {
JSONArray jsonArrayData = new JSONArray(httpResponse);
if (jsonArrayData.length() >= 1) {
for (int i = 0; i < jsonArrayData.length(); i++) {
JSONObject object = new JSONObject(jsonArrayData.get(0));
// Setting value by key json
objObject.setAtrr(object.getString("YourKey"));
}
}
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return objObject;
}