Beginner JSON question - TreeGadget to JSON

Just starting out? Need help? Post your questions and find answers here.
wombats
Enthusiast
Enthusiast
Posts: 720
Joined: Thu Dec 29, 2011 5:03 pm

Beginner JSON question - TreeGadget to JSON

Post by wombats »

Hi,

I'm trying to wrap my head around JSON. Does anyone have an example of turning a TreeGadget contents into a JSON file and then back into a TreeGadget? So, basically saving and loading the TreeGadget contents into JSON format.

Code: Select all

#Window = 0
#Tree = 0

If OpenWindow(#Window, 0, 0, 300, 500, "TreeGadget", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
  TreeGadget(#Tree, 10, 10, 280, 480)
  
  AddGadgetItem(#Tree, -1, "Item", 0, 0)
  AddGadgetItem(#Tree, -1, "Folder", 0, 0)
  AddGadgetItem(#Tree, -1, "Item", 0, 1)
  AddGadgetItem(#Tree, -1, "Folder", 0, 1)
  AddGadgetItem(#Tree, 5, "Item", 0, 2)
  AddGadgetItem(#Tree, -1, "Item", 0, 0)
  AddGadgetItem(#Tree, -1, "Folder", 0, 0)
  AddGadgetItem(#Tree, -1, "Item", 0, 1)
  AddGadgetItem(#Tree, -1, "Folder", 0, 1)
  AddGadgetItem(#Tree, -1, "Item", 0, 2)
  AddGadgetItem(#Tree, -1, "Item", 0, 0)
  
  For i = 0 To CountGadgetItems(#Tree) - 1
    SetGadgetItemState(#Tree, i, #PB_Tree_Expanded)
  Next
  
  If CreateJSON(0)
    
    For i = 0 To CountGadgetItems(#Tree) - 1
      Item = SetJSONObject(JSONValue(0))
      SetJSONString(AddJSONMember(Item, GetGadgetItemText(#Tree, i)), GetGadgetItemText(#Tree, i))
    Next
    
    Debug ComposeJSON(0)
    
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
  
EndIf
I have no clue what I'm doing, honestly. :oops:

Thanks.
User avatar
kenmo
Addict
Addict
Posts: 2049
Joined: Tue Dec 23, 2003 3:54 am

Re: Beginner JSON question - TreeGadget to JSON

Post by kenmo »

TreeGadget to JSON back to TreeGadget... that's a fun one :)

This saves a TreeGadget to JSON text

Code: Select all

OpenWindow(0, 0, 0, 300, 500, "TreeGadget", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
  TreeGadget(0, 10, 10, 280, 480)
    AddGadgetItem(0, -1, "Item 1", 0, 0)
    AddGadgetItem(0, -1, "Folder A", 0, 0)
    AddGadgetItem(0, -1, "Item 2", 0, 1)
    AddGadgetItem(0, -1, "Folder B", 0, 1)
    AddGadgetItem(0, 5, "Item 3", 0, 2)
    AddGadgetItem(0, -1, "Item 4", 0, 0)
    AddGadgetItem(0, -1, "Folder C", 0, 0)
    AddGadgetItem(0, -1, "Item 5", 0, 1)
    AddGadgetItem(0, -1, "Folder D", 0, 1)
    AddGadgetItem(0, -1, "Item 6", 0, 2)
    AddGadgetItem(0, -1, "Item 7", 0, 0)
    For i = 0 To CountGadgetItems(0) - 1
      SetGadgetItemState(0, i, #PB_Tree_Expanded)
    Next

Procedure.i CreateJSONFromTreeGadget(JSON.i, Gadget.i)
  Protected Result.i = CreateJSON(JSON)
  If (Result)
    If (JSON = #PB_Any)
      JSON = Result
    EndIf
    *Array = SetJSONArray(JSONValue(JSON))
    NewList PrevArray.i()
    Level.i = 0
    n.i = CountGadgetItems(Gadget)
    i.i = 0
    While (i < n)
      NewLevel.i = GetGadgetItemAttribute(Gadget, i, #PB_Tree_SubLevel)
      
      While (NewLevel > Level) ; We're on a deeper sublevel, so insert a new array
        AddElement(PrevArray()) : PrevArray() = *Array
        *Array = AddJSONElement(*Array)
        SetJSONArray(*Array)
        Level + 1
      Wend
      
      While (NewLevel < Level) ; We're back to the parent sublevel, so return to that array
        *Array = PrevArray()
        DeleteElement(PrevArray())
        Level - 1
      Wend
      
      SetJSONString(AddJSONElement(*Array), GetGadgetItemText(Gadget, i)) ; Add new item
      i + 1
    Wend
  EndIf
  ProcedureReturn (Result)
EndProcedure

If CreateJSONFromTreeGadget(0, 0)
  Output.s = ComposeJSON(0, #PB_JSON_PrettyPrint)
  Debug Output
  If CreateFile(1, GetTemporaryDirectory() + "tree.json")
    WriteString(1, Output)
    CloseFile(1)
  EndIf
EndIf

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
and this loads JSON text into a TreeGadget:

Code: Select all

OpenWindow(0, 0, 0, 300, 500, "TreeGadget", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
  TreeGadget(0, 10, 10, 280, 480)

Procedure FillTreeGadgetFromJSON(JSON.i, Gadget.i)
  ClearGadgetItems(Gadget)
  *Array = JSONValue(JSON)
  NewList PrevArray.i()
  NewList PrevIndex.i()
  i.i = 0
  Level.i = 0
  If JSONType(*Array) = #PB_JSON_Array
    n.i = JSONArraySize(*Array)
    While (i < n)
      Select (JSONType(GetJSONElement(*Array, i)))
        Case #PB_JSON_String
          AddGadgetItem(Gadget, -1, GetJSONString(GetJSONElement(*Array, i)), #Null, Level)
          i + 1
        Case #PB_JSON_Array
          AddElement(PrevArray()) : PrevArray() = *Array
          AddElement(PrevIndex()) : PrevIndex() = i
          *Array = GetJSONElement(*Array, i)
          n.i = JSONArraySize(*Array)
          i = 0
          Level + 1
        Default
          i + 1
      EndSelect
      While (i = n) ; Close
        If (ListSize(PrevArray())) ; Go back to previous level
          *Array = PrevArray()
          DeleteElement(PrevArray())
          n.i = JSONArraySize(*Array)
          i = PrevIndex() + 1
          DeleteElement(PrevIndex())
          Level - 1
        Else ; No more levels to go back to
          Break
        EndIf
      Wend
    Wend
  EndIf
  n = CountGadgetItems(Gadget)
  For i = 0 To n - 1
    SetGadgetItemState(Gadget, i, #PB_Tree_Expanded)
  Next
EndProcedure

If ReadFile(1, GetTemporaryDirectory() + "tree.json")
  Input.s = ReadString(1, #PB_File_IgnoreEOL)
  If ParseJSON(0, Input)
    FillTreeGadgetFromJSON(0, 0)
  EndIf
  CloseFile(1)
EndIf

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
wombats
Enthusiast
Enthusiast
Posts: 720
Joined: Thu Dec 29, 2011 5:03 pm

Re: Beginner JSON question - TreeGadget to JSON

Post by wombats »

Sorry, I haven't checked back on this topic. I've been avoiding this part of my program...heh. JSON gives me such a headache.

I'm trying to adapt your example so I end up with a JSON structure something like this:

Code: Select all

{
  "data": [
    {
      "name": "Item 1",
      "type": "item"
    },
    {
      "name": "Folder A",
      "type": "folder",
      "expanded": false,
      "contents": [
        {
          "name": "Item 3",
          "type": "item"
        },
        {
          "name": "Folder B",
          "type": "folder",
          "expanded": true,
          "contents": []
        }
        ]
    },
    {
      "name": "Item 2",
      "type": "item"
    }
  ]
}

Code: Select all

#tree_folder_type = 1

OpenWindow(0, 0, 0, 300, 500, "TreeGadget", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
  TreeGadget(0, 10, 10, 280, 480)
    AddGadgetItem(0, -1, "Item 1", 0, 0)
    AddGadgetItem(0, -1, "Folder A", 0, 0) : SetGadgetItemData(0, CountGadgetItems(0) - 1, #tree_folder_type)
    AddGadgetItem(0, -1, "Item 3", 0, 1)
    AddGadgetItem(0, -1, "Folder B", 0, 1) : SetGadgetItemData(0, CountGadgetItems(0) - 1, #tree_folder_type)
    AddGadgetItem(0, -1, "Item 2", 0, 0)
    For i = 0 To CountGadgetItems(0) - 1
      SetGadgetItemState(0, i, #PB_Tree_Expanded)
    Next

Procedure.i CreateJSONFromTreeGadget(JSON.i, Gadget.i)
  Protected Result.i = CreateJSON(JSON)
  If (Result)
    If (JSON = #PB_Any)
      JSON = Result
    EndIf
    *Array = SetJSONArray(JSONValue(JSON))
    NewList PrevArray.i()
    Level.i = 0
    n.i = CountGadgetItems(Gadget)
    i.i = 0
    While (i < n)
      NewLevel.i = GetGadgetItemAttribute(Gadget, i, #PB_Tree_SubLevel)
      
      While (NewLevel > Level) ; We're on a deeper sublevel, so insert a new array
        AddElement(PrevArray()) : PrevArray() = *Array
        json_folder = SetJSONObject(AddJSONElement(*Array))
        SetJSONString(AddJSONMember(json_folder, "name"), GetGadgetItemText(0, i))
        SetJSONString(AddJSONMember(json_folder, "type"), "folder")
        json_folder_contents = SetJSONArray(AddJSONMember(json_folder, "contents"))
        SetJSONArray(json_folder_contents)
        Level + 1
      Wend
      
      While (NewLevel < Level) ; We're back to the parent sublevel, so return to that array
        *Array = PrevArray()
        DeleteElement(PrevArray())
        Level - 1
      Wend
      
      If GetGadgetItemData(0, i) <> #tree_folder_type
        SetJSONString(AddJSONElement(*Array), GetGadgetItemText(Gadget, i)) ; Add new item
      EndIf
      i + 1
    Wend
  EndIf
  ProcedureReturn (Result)
EndProcedure

If CreateJSONFromTreeGadget(0, 0)
  Output.s = ComposeJSON(0, #PB_JSON_PrettyPrint)
  Debug Output
  If CreateFile(1, GetTemporaryDirectory() + "tree.json")
    WriteString(1, Output)
    CloseFile(1)
  EndIf
EndIf

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Yeah, I still have no idea what I'm doing with JSON. :oops:
User avatar
kenmo
Addict
Addict
Posts: 2049
Joined: Tue Dec 23, 2003 3:54 am

Re: Beginner JSON question - TreeGadget to JSON

Post by kenmo »

I think this gives what you want, except for the exact order.

Code: Select all

Procedure.i CreateJSONFromTreeGadget(JSON.i, Gadget.i)
  Protected Result.i = CreateJSON(JSON)
  If (Result)
    If (JSON = #PB_Any)
      JSON = Result
    EndIf
    *MainObj = SetJSONObject(JSONValue(JSON))
    *Array = SetJSONArray(AddJSONMember(*MainObj, "data"))
    NewList PrevArray.i()
    Level.i = 0
    n.i = CountGadgetItems(Gadget)
    i.i = 0
    While (i < n)
      NewLevel.i = GetGadgetItemAttribute(Gadget, i, #PB_Tree_SubLevel)
      While (NewLevel < Level)
        *Array = PrevArray()
        DeleteElement(PrevArray())
        Level - 1
      Wend
      If (GetGadgetItemData(Gadget, i) = #tree_folder_type)
        *Obj = SetJSONObject(AddJSONElement(*Array))
        SetJSONString(AddJSONMember(*Obj, "name"), GetGadgetItemText(Gadget, i))
        SetJSONString(AddJSONMember(*Obj, "type"), "folder")
        SetJSONBoolean(AddJSONMember(*Obj, "expanded"), GetGadgetItemState(Gadget, i) & #PB_Tree_Expanded)
        AddElement(PrevArray()) : PrevArray() = *Array
        *Array = SetJSONArray(AddJSONMember(*Obj, "contents"))
        Level + 1
      Else
        *Obj = SetJSONObject(AddJSONElement(*Array))
        SetJSONString(AddJSONMember(*Obj, "name"), GetGadgetItemText(Gadget, i))
        SetJSONString(AddJSONMember(*Obj, "type"), "item")
      EndIf
      i + 1
    Wend
  EndIf
  ProcedureReturn (Result)
EndProcedure
The PB JSON library does not guarantee the order of Object members... like "name", "type", "expanded", "contents"... as posted here:
www.purebasic.fr/english/viewtopic.php?f=13&t=68237
wombats
Enthusiast
Enthusiast
Posts: 720
Joined: Thu Dec 29, 2011 5:03 pm

Re: Beginner JSON question - TreeGadget to JSON

Post by wombats »

Thank you so much! I think this is exactly what I need...I could not wrap my head around it at all. I'm getting used to the JSON library now, and actually liking it a lot. I was using XML, but I prefer JSON as it seems more compact.
ShadowStorm
Enthusiast
Enthusiast
Posts: 303
Joined: Tue Feb 14, 2017 12:07 pm

Re: Beginner JSON question - TreeGadget to JSON

Post by ShadowStorm »

Hello,

Thanks a lot for his codes :)
Do you know how to read and fill the TreeGadget with this Json ? I tried with the read code, but it doesn't work.

Code: Select all

{
  "data": [
    {
      "name": "Item 1",
      "type": "item"
    },
    {
      "name": "Folder A",
      "type": "folder",
      "expanded": false,
      "contents": [
        {
          "name": "Item 3",
          "type": "item"
        },
        {
          "name": "Folder B",
          "type": "folder",
          "expanded": true,
          "contents": []
        }
        ]
    },
    {
      "name": "Item 2",
      "type": "item"
    }
  ]
}
I am French, I do not speak English.
My apologies for the mistakes.

I have sometimes problems of expression
I am sometimes quite clumsy, please excuse me and let me know.
wombats
Enthusiast
Enthusiast
Posts: 720
Joined: Thu Dec 29, 2011 5:03 pm

Re: Beginner JSON question - TreeGadget to JSON

Post by wombats »

It requires some changes:

Code: Select all

Procedure FillTreeGadgetFromJSON(JSON.i, Gadget.i)
  Protected element.i, name.s
  ClearGadgetItems(Gadget)
  *Array = GetJSONMember(JSONValue(JSON), "data")
  Debug JSONArraySize(*array)
  NewList PrevArray.i()
  NewList PrevIndex.i()
  i.i = 0
  Level.i = 0
  If JSONType(*Array) = #PB_JSON_Array
    n.i = JSONArraySize(*Array)
    While (i < n)
      element = GetJSONElement(*Array, i)
      Select GetJSONString(GetJSONMember(element, "type"))
        Case "item"
          Define name.s = GetJSONString(GetJSONMember(element, "name"))
          AddGadgetItem(Gadget, -1, name, #Null, Level)
          i + 1
        Case "folder"
          Define name.s = GetJSONString(GetJSONMember(element, "name"))
          AddGadgetItem(Gadget, -1, name, #Null, Level)
          AddElement(PrevArray()) : PrevArray() = *Array
          AddElement(PrevIndex()) : PrevIndex() = i
          *Array = GetJSONMember(GetJSONElement(*Array, i), "contents")
          n.i = JSONArraySize(*Array)
          i = 0
          Level + 1
      EndSelect
      While (i = n) ; Close
        If (ListSize(PrevArray())) ; Go back to previous level
          *Array = PrevArray()
          DeleteElement(PrevArray())
          n.i = JSONArraySize(*Array)
          i = PrevIndex() + 1
          DeleteElement(PrevIndex())
          Level - 1
        Else ; No more levels to go back to
          Break
        EndIf
      Wend
    Wend
  EndIf
  n = CountGadgetItems(Gadget)
  For i = 0 To n - 1
    SetGadgetItemState(Gadget, i, #PB_Tree_Expanded)
  Next
EndProcedure
ShadowStorm
Enthusiast
Enthusiast
Posts: 303
Joined: Tue Feb 14, 2017 12:07 pm

Re: Beginner JSON question - TreeGadget to JSON

Post by ShadowStorm »

Thx :D
I am French, I do not speak English.
My apologies for the mistakes.

I have sometimes problems of expression
I am sometimes quite clumsy, please excuse me and let me know.
Post Reply