How can I sort JSON by ID?

Can you give a sample of an equivalent structured JSON, showing at least two IDs?

I agree that Comparator is probably the way to go. Depending on your data structure, something like:

  1. create a Comparator that checks two JSONObjects and returns the difference of their id fields.
  2. load your JSONArray of JSONObjects into an ArrayList myList
  3. call Collections.sort(myList, idComparator).
  4. Loop over the sorted JSONObjects and write them into a single JSONArray.
1 Like

AD 1

Up to now I just work with the JSON object. I don’t have a class / objects/ Arraylist of it.

Not sure what you mean?

Can I say

Arraylist <JSONOBJECT> arrlist1 = new Arraylist ();

Do you mean this?

AD 3

Do I rebuild the entire list from scratch?

See also

That doesn’t work at all

Can you please post a simple example?

Are you trying to sort the JSON objects in your other linked post by their number keys?

Solved

(I sorted a more simple ArrayList toolTimers first instead of sorting the JSON. )


import java.util.Collections; 
import java.util.Comparator;  

...


// vars for measuring Time (Space Bar and e)
ArrayList<ToolTimer> toolTimers = new ArrayList<ToolTimer>(); 

.....
  // this sorts 
  Collections.sort(toolTimers, new TimerComparator());

....




class TimerComparator implements Comparator<ToolTimer> {
  @Override
    public int compare (ToolTimer a, ToolTimer b) {

    if (a.timeArticleIndex.equals("") )
      println("equals ++++++++++++++++++++++++");

    //if a<b return -1;
    //if a==b return 0;
    //else return 1; 
    //return a.timeArticleIndex < b.timeArticleIndex ? -1 : 
    //  a.timeArticleIndex == b.timeArticleIndex ? 0 :
    //  1;

    return a.timeArticleIndex.compareToIgnoreCase( b.timeArticleIndex);
  }
}//class
1 Like

thanks for coming back

Solved

(I sorted a more simple ArrayList toolTimers first instead of sorting the JSON. )

thank you very much!

1 Like

Sorry I just want to apply this sort to my JSONArray

The JSONArray consists of JSONObjects. Each of those has an id, by which I want to sort.

that’s what I try

class JSONComparator implements Comparator<JSONArray> {
  @Override
    public int compare (JSONArray a, JSONArray b) {

    //if (a.timeArticleIndex.equals("") )
    //  println("equals ++++++++++++++++++++++++");

    //if a<b return -1;
    //if a==b return 0;
    //else return 1; 
    //return a.timeArticleIndex < b.timeArticleIndex ? -1 : 
    //  a.timeArticleIndex == b.timeArticleIndex ? 0 :
    //  1;

    return a.getJSONObject().getString("id").compareToIgnoreCase( b.getJSONObject().getString("id") );
  }
}//class

Is it possible?

The Error message

It says

The function “getJSONObject()” expects parameters like: “getJSONObject(int)”

for this line:


    return a.getJSONObject().getString("id").compareToIgnoreCase( b.getJSONObject().getString("id") );

but which parameter do I havee to put there: a.getJSONObject()

thank you!

Chrisir

Comparator sorts units. If you have a JSONArray of JSONObjects, you need to sort those objects in pairwise comparisons. This requires a List data structure that contains them. So:

  1. copy the objects from the JSONArray to a List,
  2. sort the List object, passing .sort() your Comparator for JSONObjects so it will sort in that way
  3. copy the objects from the now-sorted List into a new JSONArray.
1 Like

Hm.

But when I have a Arraylist of
Jsonobject, I still have to use a.getString(„id“) in the comparator class?

Will this work?

And do I have to make a copy function
to fill the jsonobject for bringing it in the arraylist?

Keep in mind what a Comparator does.

List<Foo> myfoos;
Comparator<Foo> fooComp;
myfoos.sort(fooComp); // now your list of Foos is sorted

sort() on a list of Foos takes a Comparator that works on pairs of individual Foos, Foo a, Foo b – the sort method uses the Comparator throughout the list until all the Foos are sorted. So your comparator should be for JSONObject a, JSONObject b, like this (untested):

class JSONObjectIDComparator implements Comparator<JSONObject> {
  @Override
    public int compare (JSONObject a, JSONObject b) {
      return a.getInt("id") - b.getInt("id");
    }
}

So. Given

  1. a JSONArray of JSONObjects, json
  2. a class JObjComparator implements Comparator // NOT JSONArray

and then given that you have loaded your objects into a List (ArrayList, etc):

JSONArray --> List myobjs;

then (pseudocode)

// sort your list
myobjs.sort(new JSONObjectIDComparator());

// create an array to put the sorted list in
jsonSorted = new JSONArray();

// append the objects in order
for(JSONObject obj : myobjs){
  jsonA.append(obj)
}

// now your sorted list of objects are loaded in a JSONArray
1 Like

This works.

Thank you so much!

Question

ok, I have a few article IDs that are very long.

like 8329141234

I’d like to treat them as long instead of int

But how can I achieve this?

I’d like to use long() (like int()) on a String, but long() doesn’t exist

(also I don’t know how to say 123L (using “L”) as suggested here: https://processing.org/reference/long.html)

It is supposed to work in the context below

Thank you again!

Great Work!

Chrisir

class JSONComparator implements Comparator<JSONObject> {
  @Override
    public int compare (JSONObject a, JSONObject b) {

    //if a<b return -1;
    //if a==b return 0;
    //else return 1; 
    int aIndex= int(   a.getString("id").replace("-", ""));   /// !!!!!!
    int bIndex= int(   b.getString("id").replace("-", "")); /// !!!!!!
    return aIndex < bIndex ? -1 :        /// !!!!!!
      aIndex == bIndex ? 0 :
      1;
  }
}//class
1 Like

float() is just a helper function in Processing – which is standardized on float, so it doesn’t have it long().

Use Long.valueOf() for your strings, and Long.compare() to compare two longs. (untested)

class JSONComparator implements Comparator<JSONObject> {
  @Override
    public int compare (JSONObject a, JSONObject b) {
      return Long.compare(Long.valueOf(a.getString("id")), Long.valueOf(b.getString("id")));
    }
}

Edit: fixed up Long.compare line

1 Like

That’s working.

Besides very long article IDs like here I also have another kind of IDs that contain letters like
hlm123. Long crashes here but int doesn’t

In theory I could treat the 2 cases of IDs separately within the same comparator class, right?

So how do you want these sorted? As Strings? Or are there specific rules to the prefixes, like that they are always 3 letters long, and do you want to sort the prefixes alphabetically and the suffixes numerically?

sort as strings, alpha

abc123
hlm123
hml3

vs alpha / num

abc123
hml3
hlm123

1 Like

Ok, so it would be cool to have a sort method with JSONArray

How can I evaluate whether a String is numeric? (Contains only numbers?)

like s1.isNumeric() of type boolean

There are lots of ways of doing this in Java. The best solutions depend on the specific use case. Do you need to support negative numbers? Can they be a decimal, and is it localized (. vs , etc)? Will there be scientific notation?

You could submit a proposed change – processing/core/src/processing/data/JSONArray.java at master · processing/processing · GitHub

Or if you don’t want a wrapper function, you can extend JSONArray yourself. Here is an example based on the JSONArray reference example, but using a simple JSONObject id String comparator as in our discussion.

/**
 * JSONArraySorting
 * 2019-12 Extend JSONArray and add a custom sort
 */

// begin with the reference JSONArray example:
// https://processing.org/reference/JSONArray.html

import java.util.Collections;  // added
import java.util.Comparator;   // added 

String[] species = { "Capra hircus", "Panthera pardus", "Equus zebra" };
String[] names = { "Goat", "Leopard", "Zebra" };
JSONArraySortable values;            // change to extended class

void setup() {
  values = new JSONArraySortable();  // change to extended class
  for (int i = 0; i < species.length; i++) {
    JSONObject animal = new JSONObject();
    animal.setString("id", ""+(species.length-i));  // number w/Strings, 3-2-1
    animal.setString("species", species[i]);
    animal.setString("name", names[i]);
    values.setJSONObject(i, animal);
  }
  saveJSONArray(values, "data/new.json");   // saves 3-2-1
 
  // now sort the array by its object "id" keys and save it again
  values.sort();
  saveJSONArray(values, "data/new2.json");  // saves 1-2-3
  
}

class JSONArraySortable extends JSONArray {
  
  // pairwise comparison logic for sort is in the Comparator
  class JSONComparator implements Comparator<JSONObject> {
    @Override
      public int compare (JSONObject a, JSONObject b) {
      return Long.compare(Long.valueOf(a.getString("id")), Long.valueOf(b.getString("id")));
    }
  }
  
  // utility -- sort will need to get all objects from private ArrayList
  ArrayList<JSONObject> getAll() {
    ArrayList<JSONObject> myobjs = new ArrayList<JSONObject>();
    for (int i=0; i<this.size(); i++) {
      myobjs.add((JSONObject)this.get(i));
    }
    return myobjs;
  }
  
  // utility -- sort will need to clear all objects from private ArrayList
  public void clear() {
    for (int i=this.size()-1; i>=0; i--) {
      this.remove(i);
    }
  }
  
  // sort by getting all objects, sorting with comparator, clearing, and appending
  public void sort() {
    ArrayList<JSONObject> myobjs = this.getAll();
    Collections.sort(myobjs, new JSONComparator());
    this.clear();
    for (int i=0; i<myobjs.size(); i++) {
      this.append(myobjs.get(i));
    }
  }
}
1 Like