"tipolistView.setAdapter(listViewArrayAdapter)Is it possible to sort a JsonArray by a key?
I mean, I have a listview , and it is being created this way:
{"id":"1","nome":"glamourhood","tipo":"1"},
{"id":"2","nome":"Face da Mia","tipo":"2"},
{"id":"5","nome":"Team Transformerz","tipo":"3"},
{"id":"6","nome":"Face da Team de novo","tipo":"4"},
{"id":"7","nome":"Tiago Faria Fitness","tipo":"5"},
{"id":"8","nome":"Nuno Soares","tipo":"6}
And I wanted it sorted by "tipo" from smaller to bigger, or even better : by type * id (that would be awesome).
Is this achievable on Android?
deserialize your json into objects, like
(assumed these are movie titles)
#Serializable
public class Movie {
private int id;
#SerializedName("nome")
private String name;
private int tipo;
public Movie();
//getter & setter
}
For deserializing you could use GSON for instance. I've added an example for mapping json fields to different fields in an object (nome and name) when using GSON.
I can't come up with code for deserializing right now, but you will find plenty sources on the web. It must be somethiong like:
final Movie movie = gson.fromJson(yourJsonInputReader, Movie.class);
After deserializing those JSONs to objects, you may have a List<Movie> movies. Now you could sort this list in any way you want, use a CustomCoparator for this purpose.
public class MovieComparator implements Comparator<Movie>{
public enum Field {
ID, TIPO;
}
private Field field;
public MovieComparator(Field field) {
this.field = field;
}
#Override
public int compare(Movie mov1, Movie mov2) {
int comparison = 0;
switch(field) {
case ID:
comparison = mov1.getId().compareTo(mov2.getId());
case TIPO:
comparison = mov1.getTipo().compareTo(mov2.getTipo());
}
return comparison;
}
Then use it like:
Collections.sort(movies, new MovieComparator(MovieComparator.Field.ID));
Let me know if this works out or not, can't check it, because spending time with my son ;)
Related
Edit
I managed to insert only the outer JSON object. Couldn't find information on how to insert nested objects. Each object has primitive fields in it. These objects can be seen in the JSON sample below: "languages" and "currencies". I also wonder how to deal with the "latlng" array within the outer JSON object, but it's probably better to handle these issues one at a time.
The code I got for inserting a primitive value in the outer JSON object:
Gson gson = new Gson();
Type listType = new TypeToken<List<Country>>(){}.getType();
List<Country> countriesList = gson.fromJson(jsonString, listType);
for(Country country : countriesList) {
ContentValues insertValues = new ContentValues();
insertValues.put(Country.NAME, country.getName());
//more insertions
}
The original question
I parsed a nested JSON with GSON (probably incorrectly since it's my first time). Now I'm trying to insert it to SQLite. Couldn't find what needs to be written next. When I write the for loop for the insertion I get the error cannot find symbol class Country. Couldn't find relevant guidance online so I hope anyone can help in how to move forward.
That's where the issue begins:
Country[] countriesArray = gson.fromJson(jsonString, Country[].class);
for (int i = 0; i < countriesArray.length(); i++) {
...
}
countriesArray.length() is marked as an error: cannot find symbol class Country.
One object from the JSON:
[
{
"name":"Afghanistan",
"topLevelDomain":[
".af"
],
"callingCodes":[
"93"
],
"capital":"Kabul",
"region":"Asia",
"subregion":"Southern Asia",
"population":27657145,
"latlng":[
33.0,
65.0
],
"demonym":"Afghan",
"area":652230.0,
"gini":27.8,
"timezones":[
"UTC+04:30"
],
"nativeName":"افغانستان",
"numericCode":"004",
"currencies":[
{
"name":"Afghan afghani",
"symbol":"؋"
}
],
"languages":[
{
"name":"Pashto",
"nativeName":"پښتو"
},
{
"name":"Uzbek",
"nativeName":"Oʻzbek"
},
{
"name":"Turkmen",
"nativeName":"Türkmen"
}
],
"translations":{
"de":"Afghanistan",
},
"flag":"https://restcountries.eu/data/afg.svg",
"cioc":"AFG"
},
The model classes I wrote are only for the variables objects and arrays I needed.
The model class Country.Java
public class Country implements Parcelable {
private String name;
private String capital;
private String region;
private String subregion;
private int population;
private List<Double> latlng = new ArrayList<Double>();
private double area;
private double gini;
private List<String> timezones = new ArrayList<String>();
private List<Currency> currencies = new ArrayList<Currency>();
private List<Language> languages = new ArrayList<Language>();
private String flag;
public Country() {}
//getters, setters, toString() and Parcelable methods
}
The model class Currency.Java
public class Currency implements Parcelable {
private String name;
private String symbol;
//getters, setters, toString() and Parcelable methods
}
The model class Language.Java
public class Language implements Parcelable {
private String name;
private String nativeName;
//getters, setters, toString() and Parcelable methods
}
Create a typeToken and pass it to fromJson method like following
Type listType = new TypeToken<List<Country>>(){}.getType();
List<Country> countryList = gson.fromJson(jsonArray.toString(), listType);
Use Gson TypeToken to set the return object type during JSON parse
List<Country> countries = gson.fromJson(jsonString, new TypeToken<List<Country>>(){}.getType());
for(Country country : countries) {
//Do your DB operation here
}
I am pretty weak with JSON, and probably have a silly question, and was wondering how to parse a JSON object placed inside a JSON array.
So, as of now, I have
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
To retrieve my profile params, but in my endpoints I have :
[{"Name": "this", "Email","that#gmail.com"}]
I have my endpoint set up as :
public static final String ENDPOINT_PROFILE =
BuildConfig.BASE_URL
+ "/linktojson";
which gives me the above JSON.
but the issue is the [], how do I modify this with :
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
such that I can use my profile.java model class which has
public class Profile {
#Expose
#SerializedName("Name")
private String name;
#Expose
#SerializedName("Email")
private String email;
etc...
}
Any idea how to go about this?
In the doProfileApiCall() method instead of .getObjectSingle use
.getJSONArraySingle(ProfileList.class)
Now create a new class ProfileList.java with the following code.
List<Profile> profileList = new ArrayList<>();
public List<Profile> getProfileList() {
return profileList;
}
public void setProfileList(List<Profile> profileList) {
this.profileList = profileList;
}
Change the returntype of the doProfileApiCall method to
public Single<ProfileList> doProfileApiCall()
Whenever you want to access the data use it with the list position 0, when in future you get more data, you can index the data accordingly.
Generally, if JSON root object is an array you should use List on Java side. In your case you have array so use related method:
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectListSingle(Profile.class);
Rx2ANRequest source.
Say I need to fill a Binary Search Tree with data obtained from Server. Say further that the data coming from server is a json array of nodes
"parts":[{"id":1,"name":"apple"},{"id":12,"name":"orange"},{"id":21,"name":"pen"},{"id":214,"name":"kite"}]//where each {} represents a node
How do I use GSon to read the array of Nodes into my BST?
If you recall a BST has two classes
public class BST{
private Note root;
}
public class Node{
String el;
Node left, right;
}
If BST is too hard, image something simpler
public class MyDataStructure{
private List<Part> partsList;
…
}
public class Part{
String el;
List<String> stuff;
}
How do I populate MyDataStructure with partsList using GSon on android? As a side note, I would rather help solving the MyDataStruction version of the problem.
ok.. you can use this as reference:
define a class pojo
and a Fruit(is the array/list/collection)
the pojo
class Pojo {
#Override
public String toString() {
return "Pojo [parts=" + parts + "]";
}
private List<Fruits> parts;
}
the fruit
class Fruits {
private int id;
private String name;
#Override
public String toString() {
return "[id=" + id + ", name=" + name + "]";
}
}
the implementation
String json = "{\"parts\": [{\"id\":1,\"name\":\"apple\"},{\"id\":2,\"name\":\"pear\"},{\"id\":3,\"name\":\"kiwi\"}]}";
Gson g = new Gson();
Pojo p = g.fromJson(json, Pojo.class);
System.out.println(p);
the MyDataStructure population
add to the pojo a setter getter so you can work with the list, add too setter and getter for the fruit class so you can get the id and the name..
so in the pojo object p you can do p.getList() and iterate over the elements
Something like:
Pojo p = g.fromJson(json, Pojo.class);
System.out.println(p);
for (Fruits f : p.getParts()) {
System.out.println(f.getId());
System.out.println(f.getName());
}
I'm using realm to store my data on Android. Awesome framework! Now the only problem I'm now having is:
I got a array list strings with id's of Countries in my database.
Now I retrieve my Drinks that contains a relationship to countries.
Is there a way that I could to do a query like this:
String [] ids;
realm.where(Drinks.class).equalsTo("country.id", ids);
Something like that?
Or do I really need to do a query to get me all drinks and then filter the list manually?
EDIT:
My classes:
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private Country country;
}
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
}
What you want to do is possible with link queries in theory (searching for "country.id"), however link queries are slow. Also you'd need to concatenate a bunch of or() predicates together, and I would not risk that with a link query.
I would recommend using the following
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private Country country;
#Index
private String countryId;
}
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
}
And when you set the Country in your class, you also set the countryId as country.getId().
Once you do that, you can construct such:
RealmQuery<Drinks> drinkQuery = realm.where(Drinks.class);
int i = 0;
for(String id : ids) {
if(i != 0) {
drinkQuery = drinkQuery.or();
}
drinkQuery = drinkQuery.equalTo("countryId", id);
i++;
}
return drinkQuery.findAll();
Since the Realm database has added RealmQuery.in() with the version 1.2.0
I suggest using something like this.
//Drinks
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private String countryId;
//getter and setter methods
}
//Country
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
//getter and setter methods
}
The code to use inside activity/fragments to retrieve drink list
String[] countryIdArray = new String[] {"1","2","3"} //your string array
RealmQuery<Drinks> realmQuery = realm.where(Drinks.class)
.in("countryId",countryIdArray);
RealmResults<Drinks> drinkList = realmQuery.findAll();
In latest version of Realm 7+, you can use anyOf to match a field against a list of values.
anyOf("name", new String[]{"Jill", "William", "Trillian"})
in older versions, use in instead of anyOf and with kotlin use oneOf instead of in.
see this issue
To match a field against a list of values, use in. For example, to find the names “Jill,” “William,” or “Trillian”, you can use in("name", new String[]{"Jill", "William", "Trillian"}). The in predicate is applicable to strings, binary data, and numeric fields (including dates).
Doc.-> https://realm.io/docs/java/latest#queries
I would like to know a way to store an image and associated text in something like a List. I tried doing something like this
List<NameValuePair>cars = new ArrayList<NameValuePair>();
cars.add(new BasicNameValuePair("Hyundai Elantra",Integer.toString(R.drawable.hyundai_elantra)));
I know this is wrong but I'm posting it so you get an idea of what I'm trying to achieve.
It looks like the best thing for you would be to create a custom class called Car to store each car, and then create an ArrayList<Car> to store the data.
Here is what your Car class would look like:
public class Car
{
public String type;
public int imageID;
public Car(String t, int i)
{
type = t;
imageID = i;
}
public String toString()
{
return type + " " + String.valueOf(imageID);
}
}
Then you would declare the ArrayList, and add values:
ArrayList<Car> carList = new ArrayList<Car>();
carList.add(new Car("Hyundai Elantra", R.drawable.hyundai_elantra));
carList.add(new Car("Lexus RX350", R.drawable.lexus_rx350));
Then, you could iterate through the list when you want to populate your UI:
for (Car c : carList){
String s = c.type;
int image = c.imageID;
//use the values.......
}
Note that you could use this ArrayList as the data source for a custom adapter for displaying the text and images in a ListView, if that's what you're looking to do.
you can create a class named NameValue with Textand Image and you can declare an array list as follows
List<NameValue >cars = new ArrayList<NameValue >();