Android Question I tried to read json using latest tutorial with no luck

jaraiza

Active Member
Licensed User
Longtime User
Hi,

I've found this example in the forum

B4X:
Sub DownloadQuote
   Dim j As HttpJob
   j.Initialize("", Me) 'name is empty as it is no longer needed
   j.Download("http://quotesondesign.com/wp-json/posts?filter[orderby]=rand")
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     'The result is a json string. We parse it and log the fields.
     Dim jp As JSONParser
     jp.Initialize(j.GetString)
     Dim quotes As List = jp.NextArray
     For Each quot As Map In quotes
       Log("Title: " & quot.Get("title"))
       Log("Content: " & quot.Get("content"))
     Next
   End If
   j.Release
End Sub

I've reduced the example to this to try to debug

B4X:
    Dim jp As JSONParser
    Dim jsonSaldo As String
    jsonSaldo = "{""saldoCC"":""328.00"",""saldoSyR"":""30.00"",""saldoCB"":""0.00"",""cbPoints"":10.0,""Msg"":""OK""}"
    jp.Initialize(jsonSaldo)
    Log("jsonSaldo: " & jsonSaldo)
    Dim quotes As List = jp.NextArray
    For Each quot As Map In quotes
      'Log("saldoCC: " & quot.Get("saldoCC"))
    Next

I get an error at "jp.NextArray" assignation

B4X:
jsonSaldo: {"saldoCC":"328.00","saldoSyR":"30.00","saldoCB":"0.00","cbPoints":10.0,"Msg":"OK"}
Error occurred on line: 112 (Main)
java.lang.RuntimeException: JSON Array expected.
    at anywheresoftware.b4a.objects.collections.JSONParser.NextArray(JSONParser.java:79)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at mx.cclogistics.recargame.multi.main.afterFirstLayout(main.java:105)
    at mx.cclogistics.recargame.multi.main.access$000(main.java:17)
    at mx.cclogistics.recargame.multi.main$WaitForLayout.run(main.java:83)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:8061)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:703)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)

Can you help me understanding where the issue is?

Thanks!
 

Sagenut

Expert
Licensed User
Longtime User
You cannot open and close so many " in a normal string.
You need to use Smart String Literal.
And that Json string looks incorrect.
Try with this
B4X:
JsonSaldo = $"{"saldoCC":"328.00","saldoSyR":"30.00","saldoCB":"0.00","cbPoints":10.0,""lMsg":"OK"}"$
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Hi,

I've found this example in the forum

B4X:
Sub DownloadQuote
   Dim j As HttpJob
   j.Initialize("", Me) 'name is empty as it is no longer needed
   j.Download("http://quotesondesign.com/wp-json/posts?filter[orderby]=rand")
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     'The result is a json string. We parse it and log the fields.
     Dim jp As JSONParser
     jp.Initialize(j.GetString)
     Dim quotes As List = jp.NextArray
     For Each quot As Map In quotes
       Log("Title: " & quot.Get("title"))
       Log("Content: " & quot.Get("content"))
     Next
   End If
   j.Release
End Sub

I've reduced the example to this to try to debug

B4X:
    Dim jp As JSONParser
    Dim jsonSaldo As String
    jsonSaldo = "{""saldoCC"":""328.00"",""saldoSyR"":""30.00"",""saldoCB"":""0.00"",""cbPoints"":10.0,""Msg"":""OK""}"
    jp.Initialize(jsonSaldo)
    Log("jsonSaldo: " & jsonSaldo)
    Dim quotes As List = jp.NextArray
    For Each quot As Map In quotes
      'Log("saldoCC: " & quot.Get("saldoCC"))
    Next

I get an error at "jp.NextArray" assignation

B4X:
jsonSaldo: {"saldoCC":"328.00","saldoSyR":"30.00","saldoCB":"0.00","cbPoints":10.0,"Msg":"OK"}
Error occurred on line: 112 (Main)
java.lang.RuntimeException: JSON Array expected.
    at anywheresoftware.b4a.objects.collections.JSONParser.NextArray(JSONParser.java:79)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at mx.cclogistics.recargame.multi.main.afterFirstLayout(main.java:105)
    at mx.cclogistics.recargame.multi.main.access$000(main.java:17)
    at mx.cclogistics.recargame.multi.main$WaitForLayout.run(main.java:83)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:8061)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:703)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)

Can you help me understanding where the issue is?

Thanks!

1) Use string literal as Sagenut said
2) Use NextObject because what you have is a JSON object:

B4X:
Dim m as Map = jp.NextObject
 
Upvote 0

jaraiza

Active Member
Licensed User
Longtime User
You cannot open and close so many " in a normal string.
You need to use Smart String Literal.
And that Json string looks incorrect.
Try with this
B4X:
JsonSaldo = $"{"saldoCC":"328.00","saldoSyR":"30.00","saldoCB":"0.00","cbPoints":10.0,""lMsg":"OK"}"$
Hi, thanks for the advice on String Literals. It was just an example because the real code gets the json from a SOAP Service, something like this

B4X:
Dim jsonSaldo As String
jsonSaldo = CommonFuncs.xmlGetTagContent(ResFix,"glSaldoResult")
jp.Initialize(jsonSaldo)

But I'll need that "$" notation, which I was not aware of. Thanks
 
Upvote 0

jaraiza

Active Member
Licensed User
Longtime User
1) Use string literal as Sagenut said
2) Use NextObject because what you have is a JSON object:

B4X:
Dim m as Map = jp.NextObject

That's what I need, thanks! NextObject did the trick. I was following the example with NextArray because it says "The result is a json string".

Thanks again
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
That's what I need, thanks! NextObject did the trick. I was following the example with NextArray because it says "The result is a json string".

Thanks again

Great. In order to know what it is, if it starts with a '[' and it ends with a ']' then it is a JSON Array (use NextArray) but if it starts with a '{' and ends with a "}' then it is a JSON object (use NextObject). You can also have nested JSON Arrays and JSON Objects.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
If the json begins with a { the content is a map ->
B4X:
Dim m as Map = jp.NextObject

If the json begins with a [ the content is a List ->
B4X:
Dim m as List = jp.NextArray
 
Upvote 0

jaraiza

Active Member
Licensed User
Longtime User
Thanks everyone 👍🏻

I was confused since I'm so used to C#

C#:
    public class nameList { public List<ClientesObj> clientes { get; set; } }
    public class ClientesObj {
        public string cliente { get; set; }
        public string usuario { get; set; }
        public string balance { get; set; }
        public string ID { get; set; }
        public string ParentID { get; set; }
    }


    JavaScriptSerializer ser = new JavaScriptSerializer();
    nameList AllClients = ser.Deserialize<nameList>(getClientes);

😅
 
Upvote 0
Top