B4J Question How to Unflatten List to a JSON Tree?

Mashiane

Expert
Licensed User
Hi there

Can anyone please help with a snippet to unflatten data into a json stree?

For example, this is my list of records...

B4X:
Dim arr As List
arr.Initialize
arr.Add(CreateMap("id":1 ,"parentid" : 0))
arr.Add(CreateMap("id":4 ,"parentid" : 2))
arr.Add(CreateMap("id":3 ,"parentid" : 1))
arr.Add(CreateMap("id":5 ,"parentid" : 0))
arr.Add(CreateMap("id":6 ,"parentid" : 0))
arr.Add(CreateMap("id":2 ,"parentid" : 1))
arr.Add(CreateMap("id":7 ,"parentid" : 4))
arr.Add(CreateMap("id":8 ,"parentid" : 1))
To something like...

B4X:
[
 {
  "id": 1,
  "parentid": 0,
  "children": [
   {
    "id": 2,
    "parentid": 1,
    "children": [
     {
      "id": 4,
      "parentid": 2,
      "children": [
       {
        "id": 7,
        "parentid": 4,
        "children": []
....
....
       }
 

Brandsum

Well-Known Member
Licensed User
Code:
B4X:
Dim arr As List
arr.Initialize
arr.Add(CreateMap("id":1 ,"parentid" : 0, "children": Null))
arr.Add(CreateMap("id":4 ,"parentid" : 2, "children": Null))
arr.Add(CreateMap("id":3 ,"parentid" : 1, "children": Null))
arr.Add(CreateMap("id":5 ,"parentid" : 0, "children": Null))
arr.Add(CreateMap("id":6 ,"parentid" : 0, "children": Null))
arr.Add(CreateMap("id":2 ,"parentid" : 1, "children": Null))
arr.Add(CreateMap("id":7 ,"parentid" : 4, "children": Null))
arr.Add(CreateMap("id":8 ,"parentid" : 1, "children": Null))

For Each m As Map In arr
    For Each mm As Map In arr
        If m.get("id") = mm.Get("parentid") Then
            Dim l As List
            If m.Get("children") = Null Then
                l.Initialize
            Else
                l = m.Get("children")
            End If
            l.Add(mm)
           
            m.put("children",l)
        End If
    Next
Next
Dim finalArr As List:finalArr.Initialize
For Each m As Map In arr
    If m.Get("parentid") = 0 Then finalArr.Add(m)
Next
   
Dim json As JSONGenerator
json.Initialize2(finalArr)
Log(json.ToPrettyString(4))
Output:
B4X:
[
    {
        "id": 1,
        "parentid": 0,
        "children": [
            {
                "id": 3,
                "parentid": 1,
                "children": null
            },
            {
                "id": 2,
                "parentid": 1,
                "children": [
                    {
                        "id": 4,
                        "parentid": 2,
                        "children": [
                            {
                                "id": 7,
                                "parentid": 4,
                                "children": null
                            }
                        ]
                    }
                ]
            },
            {
                "id": 8,
                "parentid": 1,
                "children": null
            }
        ]
    },
    {
        "id": 5,
        "parentid": 0,
        "children": null
    },
    {
        "id": 6,
        "parentid": 0,
        "children": null
    }
]
 
Last edited:

Mashiane

Expert
Licensed User
@Brandsum Thanks a mill. Managed to follow your logic and rewrote the main script so that I add the 'children' internally within the script

B4X:
'unflatten as list of map objects using id, parentid, data attributes
Sub Unflatten(data As List) As List
    'id, parentid, data
    Dim tree As List
    Dim mappedArr As Map
    '
    tree.Initialize
    mappedArr.Initialize
    '
    'create a temp map to hold everything with 'children' as 'data'
    For Each arrElem As Map In data
        Dim dID As String = arrElem.Get("id")
        '
        Dim children As List
        children.Initialize
        arrElem.Put("data", children)
        '
        mappedArr.Put(dID, arrElem)
    Next
    '
    For Each dID As String In mappedArr.Keys
        Dim mappedElem As Map = mappedArr.Get(dID)
        Dim parentid As String = mappedElem.Get("parentid")
        ' If the element is at the root level, add it to first level elements list.
        If parentid = "" Then
            tree.Add(mappedElem)
        Else
            'If the element is not at the root level, add it to its parent list of children.
            Dim parentElem As Map = mappedArr.Get(parentid)
            Dim children As List = parentElem.Get("data")
            children.Add(mappedElem)
            parentElem.Put("data", children)
            mappedArr.Put(parentid, parentElem)
        End If
    Next
    Return tree
End Sub
 

ThRuST

Well-Known Member
Licensed User
@Mashiane You might want to create an editor for this and share? json usually calls for a simplicity in sight-reading :)
 

Mashiane

Expert
Licensed User
@ThRuST that wouldn’t be an overkill? I needed this for my webix explorations for three of their tree based components to be able to feed data.

So it’s a tree map to json conversion and there is already a json parser here in b4x.

If perhaps my plate wasn’t full. I want to finish my html games stuff, and also side projects I’m working on.
 
Top