Android Question Sort json

miling

Member
How can I sort the following JSON based on the 'amount' in ascending order? I need a function that takes the JSON, sorts it, and returns the sorted JSON as output.

[CODE lang="json" title="Simple json"][{"service":"1","count":"110","amount":99000,"id":"1413"},{"service":"1","count":"3","amount":53000,"id":"3"},{"service":"1","country":"5","operator":"1","count":"29702","amount":63000,"id":"9"},{"service":"1","count":"605","amount":87000,"id":"95"},{"service":"1","count":"102","amount":46000,"id":"8"}][/CODE]
 
Solution
Code:
Sub Process_Globals
    Type ItemType (Service As String, Count As Int, Amount As Int, Id As Int)
    Dim msg As String = $"[{"service":"1","count":"110","amount":99000,"id":"1413"},{"service":"1","count":"3","amount":53000,"id":"3"},{"service":"1","country":"5","operator":"1","count":"29702","amount":63000,"id":"9"},{"service":"1","count":"605","amount":87000,"id":"95"},{"service":"1","count":"102","amount":46000,"id":"8"}]"$
End Sub

Sub AppStart (Args() As String)
    Dim res As List = Sort(msg.As(JSON).ToList)
    Log(res.As(JSON).ToString)
End Sub

Private Sub Sort(Input As List) As List
    Dim res As List
    res.Initialize
    For Each m As Map In Input
        res.Add(CreateItemType(m.Get("service"), m.Get("count")...
Code:
Sub Process_Globals
    Type ItemType (Service As String, Count As Int, Amount As Int, Id As Int)
    Dim msg As String = $"[{"service":"1","count":"110","amount":99000,"id":"1413"},{"service":"1","count":"3","amount":53000,"id":"3"},{"service":"1","country":"5","operator":"1","count":"29702","amount":63000,"id":"9"},{"service":"1","count":"605","amount":87000,"id":"95"},{"service":"1","count":"102","amount":46000,"id":"8"}]"$
End Sub

Sub AppStart (Args() As String)
    Dim res As List = Sort(msg.As(JSON).ToList)
    Log(res.As(JSON).ToString)
End Sub

Private Sub Sort(Input As List) As List
    Dim res As List
    res.Initialize
    For Each m As Map In Input
        res.Add(CreateItemType(m.Get("service"), m.Get("count"), m.Get("amount"), m.Get("id")))
    Next
    res.SortType("Amount", True)
    Return res
End Sub


Public Sub CreateItemType (Service As String, Count As Int, Amount As Int, Id As Int) As ItemType
    Dim t1 As ItemType
    t1.Initialize
    t1.Service = Service
    t1.Count = Count
    t1.Amount = Amount
    t1.Id = Id
    Return t1
 
Upvote 1
Solution
Hi @Erel
The output looks like this:

JSON:
[

    "[IsInitialized=true, amount=46000, count=102\n, country=null, description=null, emoji=null\n, id=8, operator=null, repeat=null\n, service=1, time=null]",

    "[IsInitialized=true, amount=53000, count=3\n, country=null, description=null, emoji=null\n, id=3, operator=null, repeat=null\n, service=1, time=null]",

    "[IsInitialized=true, amount=63000, count=29702\n, country=5, description=null, emoji=null\n, id=9, operator=1, repeat=null\n, service=1, time=null]",

    "[IsInitialized=true, amount=87000, count=605\n, country=null, description=null, emoji=null\n, id=95, operator=null, repeat=null\n, service=1, time=null]",

    "[IsInitialized=true, amount=99000, count=110\n, country=null, description=null, emoji=null\n, id=1413, operator=null, repeat=null\n, service=1, time=null]"

]

If I want it to be like this:

JSON:
[{"service":"1","count":"102","amount":46000,"id":"8"},{"service":"1","count":"3","amount":53000,"id":"3"},{"service":"1","country":"5","operator":"1","count":"29702","amount":63000,"id":"9"},{"service":"1","count":"605","amount":87000,"id":"95"},{"service":"1","count":"110","amount":99000,"id":"1413"}
]
 
Upvote 0
You are correct. I missed the step to convert the type back to map.


Please post the solut solution.

My solution is somewhat unconventional, but I am satisfied with the outcome.

[CODE lang="b4x" title="My solution"]Sub AppStart (Args() As String)

Dim res As List = Sort(msg.As(JSON).ToList)

Dim dataList As List
dataList.Initialize

For Each str As String In res
Dim jsonObject As Map
jsonObject.Initialize

Dim pairs() As String = Regex.Split(",\s*(?=\w+=)", str)
For Each pair As String In pairs
Dim keyValue() As String = Regex.Split("=", pair)
If keyValue.Length = 2 Then
Dim key As String = keyValue(0).Trim
Dim value As String = keyValue(1).Trim
jsonObject.Put(key, value)
End If
Next

dataList.Add(jsonObject)
Next

Dim sortedJsonList As List
sortedJsonList.Initialize

For Each item As Map In dataList
Dim jg As JSONGenerator
jg.Initialize(item)
sortedJsonList.Add(jg.ToString)
Next

Dim exJson As JSONGenerator
exJson.Initialize2(sortedJsonList)
Dim jsonSortResult As String = exJson.ToString
jsonSortResult = jsonSortResult.Replace($"["{\"["$,$"[{""$)
jsonSortResult = jsonSortResult.Replace($"}"]"$,"}]")
jsonSortResult = jsonSortResult.Replace($"\""$,$"""$)
jsonSortResult = jsonSortResult.Replace($"}","{"$,"},{")
Log(jsonSortResult)
End Sub[/CODE]

@Erel Now, if possible, could you please explain the proper method to me?
 
Upvote 0
I am also looking for a solution.
Then I got an idea by using SQL. Here is my solution but the output JSON contains Null values. However, it is more flexible as you can sort more than one fields.

B4X:
 #AdditionalJar: sqlite-jdbc-3.41.2.1
Sub Process_Globals
    Type KeyValueList (Keys As List, Values As List)
    Dim msg As String = $"[{"service":"1","count":"110","amount":99000,"id":"1413"},{"service":"1","count":"3","amount":53000,"id":"3"},{"service":"1","country":"5","operator":"1","count":"29702","amount":63000,"id":"9"},{"service":"1","count":"605","amount":87000,"id":"95"},{"service":"1","count":"102","amount":46000,"id":"8"}]"$
    Dim OrderList As List = Array("amount")
End Sub

Sub AppStart (Args() As String)
    Dim List1 As List = msg.As(JSON).ToList
    Dim keys As List = Array("service", "country", "operator", "count", "amount", "id")
    Dim cols As List = Array(DBUtils.DB_TEXT, DBUtils.DB_TEXT, DBUtils.DB_TEXT, DBUtils.DB_TEXT, DBUtils.DB_TEXT, DBUtils.DB_TEXT)
    'Dim cols As List = Array(DBUtils.DB_INTEGER, DBUtils.DB_INTEGER, DBUtils.DB_INTEGER, DBUtils.DB_INTEGER, DBUtils.DB_INTEGER, DBUtils.DB_INTEGER)
    Dim schema As KeyValueList = CreateKeyValueList(keys, cols)

    Dim imdb As SQL ' in-memory database
    imdb.InitializeSQLite("", ":memory:", True)
    DBUtils.CreateTable(imdb, "TempList", ConvertKeyValueList2Map(schema), "id")
    DBUtils.InsertMaps(imdb, "TempList", List1)
    
    Dim Query As String = "SELECT * FROM TempList ORDER BY " & List2CommaString(OrderList)
    Dim SortedMap As Map = DBUtils.ExecuteJSON(imdb, Query, Null, 0, cols)
    Dim root As List = SortedMap.Get("root")
    Log(root.As(JSON).ToString)
    StartMessageLoop
End Sub

Public Sub ConvertKeyValueList2Map (kvl As KeyValueList) As Map
    Dim obj As Map = CreateMap()
    For i = 0 To kvl.Keys.Size - 1
        obj.Put(kvl.Keys.Get(i), kvl.Values.Get(i))
    Next
    Return obj
End Sub

Private Sub List2CommaString (list As List) As String
    Dim SB As StringBuilder
    SB.Initialize
    For Each item In list
        If SB.Length > 0 Then SB.Append(", ")
        SB.Append(item)
    Next
    Return SB.ToString
End Sub

Public Sub CreateKeyValueList (Keys As List, Values As List) As KeyValueList
    Dim t1 As KeyValueList
    t1.Initialize
    t1.Keys = Keys
    t1.Values = Values
    Return t1
End Sub

JSON:
Waiting for debugger to connect...
Program started.
CreateTable: CREATE TABLE IF NOT EXISTS [TempList] ([service] TEXT, [country] TEXT, [operator] TEXT, [count] TEXT, [amount] TEXT, [id] TEXT PRIMARY KEY)
InsertMaps (first query out of 5): INSERT INTO [TempList] ([amount], [service], [count], [id]) VALUES (?, ?, ?, ?)
ExecuteJSON: SELECT * FROM TempList ORDER BY amount
[
    {
        "country": null,
        "amount": "46000",
        "service": "1",
        "count": "102",
        "id": "8",
        "operator": null
    },
    {
        "country": null,
        "amount": "53000",
        "service": "1",
        "count": "3",
        "id": "3",
        "operator": null
    },
    {
        "country": "5",
        "amount": "63000",
        "service": "1",
        "count": "29702",
        "id": "9",
        "operator": "1"
    },
    {
        "country": null,
        "amount": "87000",
        "service": "1",
        "count": "605",
        "id": "95",
        "operator": null
    },
    {
        "country": null,
        "amount": "99000",
        "service": "1",
        "count": "110",
        "id": "1413",
        "operator": null
    }
]
 
Upvote 0
could you please explain the proper method to me?
All that was missing was:
I missed the step to convert the type back to map.
One way to implement (I'm just including modified Sort method and additional helper sub):
Code:
Private Sub Sort(Input As List) As List
    Dim res As List
    res.Initialize
    For Each m As Map In Input
        res.Add(CreateItemType(m.Get("service"), m.Get("count"), m.Get("amount"), m.Get("id")))
    Next
    res.SortType("Amount", True)
    '
    'Convert itemtypes back to maps
    '
    Dim res2 As List
    res2.Initialize
    For Each item As ItemType In res
        res2.Add(ItemType2Map(item))
    Next
    Return res2
End Sub

Public Sub ItemType2Map(input As ItemType) As Map
    Dim m As Map
    m.Initialize
    m.Put("service", input.Service)
    m.Put("count", input.Count)
    m.Put("amount", input.Amount)
    m.Put("id", input.Id)
    Return m
End Sub
 
Upvote 3
Back
Top