Blasted JSON! Argh

Kevin

Well-Known Member
Licensed User
Longtime User
I'm finally getting around to playing with B4A more lately (came from years and years of VB 3-6) and although it's definitely easier than pure Java/Android programming, which I looked into (using Eclipse), I'm just having the hardest time with simple stuff. :BangHead:

It took me hours just to finally figure out how to 'clear' the screen when showing and hiding different views. After hours of searching and barking up the wrong tree, I finally stumbled on an errant thread here that happened to mention it. How embarrassing!

Anyhoo.... The app I'm working on now is kind of just an experiment for me to learn how to use B4A better, and I'm definitely understanding some things better than before, but I am having a problem with JSON.

It took me a while, but I finally figured out how to extract info from a JSON file located on a web server. Now I am trying to start getting my app to store information. I was initially going to use XML, but figured since I'm already using JSON a bit, why not just use that?

Below is a proposed file I would like my app to use. I would prefer it to be located on the SD card so that settings can be backed up and retained.

Here is the file:

B4X:
{
    "receiver": [
        {
            "ip": "0",
            "name": "BASEMENT"
        }
    ],
    "macro": [
        {
            "name": "Test",
            "command": "up"
        }
    ],
    "favorite": [
        {
            "name": "Test",
            "channel": "26.2"
        }
    ],
    "AppSettings": {
        "HasBeenSetup": 1,
        "NumRuns": 1,
        "LastRemote": 1,
        "LastReceiver": "BASEMENT",
        "StartOn": "Setup",
        "Haptic": 1
    }
}

It took me lots of experimenting to come up with this JSON file. I finally got it correct after using online validators, but I can't for the life of me figure out how to do two simple things:

Save info to it and retrieve info from it! I'm not even sure how to start because I'm not sure if I can include a "skeleton" config file with my app in the APK or if I would need to generate it on first run, and if so, how? Can something with this kind of structure easily be created in code? Or does one usually somehow include a copy of the file with the APK and copy it to the device's SD card through code?

In case it's not obvious, I need to be able to get and set app options (AppSettings), which are all just single values. I also want to be able to get and set "receiver" (ip address and name), "macro" (name and text/value), and "favorite" (name and text/value). These last 3 settings should be arrays (*I think*), in that there could be none or many of these in the JSON file and it needs to be able to add and remove entries, such as for "receiver". I'm pretty sure I can work THAT part out once I figure out the basics of manipulating the data in the file, but I can't wrap my brain around objects, maps, arrays and values and how they all relate to different elements in a JSON file.

I've looked through the tutorials, help file, forum, etc, and I just can't figure it out. I'd appreciate any help anyone could offer me. :sign0104: I was starting to have fun with my little project because I've always enjoyed programming but now I am just getting frustrated. (I used to spend almost all of my free time programming in VB6 until I started a family and got a bigger "job" about 6 years ago.) Now I've spent the whole day messing with this and I haven't gotten anywhere. :(

As much as I hated to come on the forum begging for help, I will say that this is definitely one of the most helpful forums I've come across, and it's much appreciated for something like B4A. While there is extensive help and samples, it just doesn't cover everything in enough detail for me to figure it all out.
 

Kevin

Well-Known Member
Licensed User
Longtime User
I'm going to look at this stuff again today with fresh eyes (haven't had much sleep lately due to working night shifts, which isn't helping me at all).

In the meantime, I don't necessarily need someone to completely write code specific to my situation, and would also be happy with sample code from another existing project that utilizes similar functionality (i.e. saving and retrieving settings to a file on the device in a similar manner). I could also do it in XML and for all I know that would be easier.

I've always preferred to just modify sample code for circumstance like this because otherwise I feel like I am reinventing the wheel so to speak. :D
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
I feel like I am getting close, but still, the problems persist:


My latest JSON code:
B4X:
{
"appdata":{
    "settings": [
        {
            "HasBeenSetup": 1,
            "NumRuns": 1,
            "LastRemote": 1,
            "LastReceiver": "TESTDEVICE",
            "StartOn": "Setup",
            "Haptic": 1
        }
    ],
    "receivers": [
        {
            "Rname": "TESTDEVICE",
            "Rip": "0.0.0.0"
        }
    ],
    "macros": [
        {
            "Mname": "TESTMACRO",
            "Mdata": "one two three"
        }
    ],
    "favorites": [
        {
            "Fname": "TESTFAV",
            "Fch": "26.2"
        }
    ]
}
}


B4A Code (Called from Activity_Create if FirstTime=True):
B4X:
Sub GetPrefs

   Dim JSON As JSONParser
   Dim jsonMap As Map
   Dim jsonResultMap As Map
   Dim jsonMap2 As Map
   Dim jsonItems As List

    listview1.Clear ' clear list of receivers from ListView
    lstSTB.Clear ' clear list of receivers from List variable

   ' Initialize JSON
    JSON.Initialize(File.ReadString(File.DirAssets, "Remote.txt"))

    ' Get Objects
    jsonMap = JSON.NextObject
   
   
   jsonResultMap=jsonMap.Get("appdata")
   
   
   ' Get App Settings
   jsonItems=jsonResultMap.Get("settings")

   For i = 0 To jsonItems.Size - 1
        jsonMap2 = jsonItems.Get(i)
        Log(jsonMap2.Get("HasBeenSetup"))
        Log(jsonMap2.Get("NumRuns"))
      Log(jsonMap2.Get("LastRemote"))
      Log(jsonMap2.Get("LastReceiver"))
      Log(jsonMap2.Get("StartOn"))
      Log(jsonMap2.Get("Haptic"))
    Next
   
   ' Get receivers
   jsonItems=jsonResultMap.Get("receivers")

   For i = 0 To jsonItems.Size - 1
        jsonMap2 = jsonItems.Get(i)
        Log(jsonMap2.Get("Rname"))
        Log(jsonMap2.Get("Rip"))
      Dim stb As DTVSTB
      stb.aFriendlyName = jsonMap2.Get ("Rname")
      stb.aIP = jsonMap2.Get ("Rip")
      lstSTB.Add (stb)
      ListView1.AddSingleLine2 (stb.aFriendlyName,stb.aIP)
    Next
   
   ' Get macros
   jsonItems=jsonResultMap.Get("macros")

   For i = 0 To jsonItems.Size - 1
        jsonMap2 = jsonItems.Get(i)
        Log(jsonMap2.Get("Mname"))
        Log(jsonMap2.Get("Mdata"))
    Next

   ' Get favorites
   jsonItems=jsonResultMap.Get("favorites")

   For i = 0 To jsonItems.Size - 1
        jsonMap2 = jsonItems.Get(i)
        Log(jsonMap2.Get("Fname"))
        Log(jsonMap2.Get("Fch"))
    Next

End Sub

The result is an error on line 835, which is:
jsonMap = JSON.NextObject

Error is "Object expected". I've tried changing it to
jsonMap = JSON.NextArray and all that does is changes the error to say that an array was expected.

As best I can tell, this should be working. Obviously something is wrong though but I can't figure out what.

Any help?
 
Last edited:
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
:sign0163:

Unfortunately I'm still stuck on this one so I worked on other stuff today. On the plus side, I got quite a bit done and it's coming along nicely. On the minus side, I still cannot save & load settings. :confused:

I feel like it is close. I just don't know why I'm getting that error now when everything looks right (as best as I can tell) with the JSON and B4A code. I must be missing something.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Can you upload your JSON text as a file? Maybe your file includes some illegal character which breaks things?

On the minus side, I still cannot save & load settings.
Saving settings should be simple. The most simple way is to store them in a Map and call File.WriteMap.

Also check the state Basic4android Search: StateManager
and the new PreferenceActivity library.
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
I saw something about the File.WriteMap function, but it seemed like it might be too simple for what I am doing with multiple arrays. I could be over-thinking it though, as that happens a lot with me.

Anyway, here is the file:

I wrote it in Windows Notepad and I also ran it through two online JSON parcers. One just tells you if it is okay, and the other breaks it down into the different elements. From what I can tell, it should be perfectly valid.

Does my B4A code look okay?
 

Attachments

  • Remote.txt
    607 bytes · Views: 245
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
As I suspected it is related to the UTF8 marking (BOM).
If you open it with Notepad++ you can see that it is encoded in UTF8.
Changing the encoding to UTF8 without BOM fixes this issue.
This marking adds three bytes at the beginning of the file which breaks the parser.

SS-2011-08-07_10.47.50.png
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
Thanks! I figured it was something simple. Sadly I had gone through Notepad++ with it and changed the encoding from ansi to UTF-8 but I didn't know about the BOM thing.


It's getting really late here so I'm not even going to look at this right now for fear that I'll never get to bed. I'm sure this will fix the issue though.

Thanks much!

I assume my B4A code all looks right?
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
Just figured I'd update the thread to say thank to Erel! That was definitely the problem and everything worked perfectly fine after changing the file's encoding. That was driving me crazy.... such a simple thing!

I appreciate the help available here, and also I appreciate B4A. The more I use it, the more I realize just how awesome it is.

I was also having some issues with several HTTP requests causing concurrent connection errors and I just stumbled on the HttpUtils module. I haven't started to switch my code over yet, but I think that is going to solve my problem.

:sign0098:
 
Upvote 0
Top