Spanish Parsear json. Lección 1 [SOLUCIONADO]

carlos7000

Active Member
Licensed User
Longtime User
Hola a todos.

Estoy tratando en aprender como parsear json

Sé que algo dentro de corchetes cuadrados es un Objeto. Algo dentro de corchetes es un Array. Un objeto puede contener otros objetos y arrays, y un Array puede contener otros arrays y objetos. ¿O era al contrario? ;-)

Sé que lo primero que hay hacer es inicializar el objeto json con la cadena a parcear.

Lo primero que intentaré hacer es obtener es el 'success' para saber si es 'true' o 'false' y luego los datos de Bid, Ask y Last de este texto:

B4X:
{"success":true,"message":"","result":{"Bid":0.01157113,"Ask":0.01158113,"Last":0.01158113}}

Lo he obtenido de https://bittrex.com/api/v1.1/public/getticker?market=BTC-LTC

La primera parte del código de b4a es esta:

B4X:
Dim json As JSONParser
Dim texto as String
Dim m as Map
dim Items as List

'Por ahora el texto lo cargo directo desde un archivo
texto = File.ReadString(File.DirAssets, "data.txt")

'Inicializo el json
json.Initialize(texto)

'Recupero el primer y único objeto
m = json.NextObject

'guardo los datos de 'result' en una lista
Items = m.Get("result")

Y hasta aquí llegué.

Para empezar el código no funciona. al ejecutarlo el programa se cierra.

He leído el tutorial https://www.b4x.com/android/forum/threads/android-json-tutorial.6923/ Pero mi ingles es pésimo y con el traductor la cosa no mejora. También mire este tutorial http://kio4.com/b4a/30Bjson.htm pero sigo sin entender del todo como parsear.

¿Alguien me podría explicar de forma sencilla como recorrer un json?

Necesito obtener los datos de Bid, Ask y Last y ponerlos en una lista. Para luego guardar los datos de Bid, Ask y Last en tres variables con los mismos nombres. No sé si me puedo evitar el paso de enviar los datos a una lista.

Saludes
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
hola!

lo que esta en results es un mapa (o un object en terminos json) asi que deberias cambiar

B4X:
'guardo los datos de 'result' en una lista // mapa
dim items as map

Items = m.Get("result")

Si tienes errores despues de corregir este, postealo para ver por que te falla.
 

carlos7000

Active Member
Licensed User
Longtime User
El nuevo código es este:

B4X:
Sub ButtonGetBTC_LTC_Click
    'Dim URL As String
    'URL = "https://bittrex.com/api/v1.1/public/getticker?market=BTC-LTC"
    'request1.InitializeGet(URL)
    'client1.Execute(request1, 1)   
   
    Dim Success As String
    Dim Bid As Float
    Dim Ask As Float
    Dim Last As Float
   
   
    Dim m As Map 'helper map For navigating
    Dim MenuItems As List
        MenuItems.Initialize
   
    Dim texto As String   
    texto = File.ReadString(File.DirAssets, "data.txt")
    'texto = "{""success"":True,""message"":"""",""result"":{""Bid"":0.01157113,""Ask"":0.01158113,""Last"":0.01158113}}"
   
    Dim json As JSONParser
    json.Initialize(texto)
   
    'Recuperamos el Objeto Raiz   
    m = json.NextObject 
   
    'Recuperamos 'success'
    Success = m.Get("success")
   
   
    m = m.Get("result")
       
    Bid  = m.get("Bid")  'Recuperamos 'Bid'
    Ask  = m.get("Ask")  'Recuperamos 'Ask'
    Last = m.get("Last") 'Recuperamos 'Last'

    'Mostramos los Datos
    EditTextOut.Text = "Success: " & Success & CRLF
    EditTextOut.Text = EditTextOut.Text & "Bid:  " & Bid & CRLF
    EditTextOut.Text = EditTextOut.Text & "Ask:  " & Ask & CRLF
    EditTextOut.Text = EditTextOut.Text & "Last: " & Last & CRLF
End Sub

Funciona casi "Perfecto". Pero el texto mostrado muestra números decimales que NO vienen en el json

GWKAGKdc6F_j_uAb-CHJFCAGf09j5IaPlyqUNuVaW8I


¿Cuál sera el problema?
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
bien!

cambia las declaraciones FLOAT por DOUBLE, FLOAT es mas "cientifico" y hace algunos calculos raros, Double es el correcto para mostrar datos decimales.

B4X:
Dim Bid As Float ' double
    Dim Ask As Float ' double
    Dim Last As Float ' double
 

carlos7000

Active Member
Licensed User
Longtime User
Sí, El problema era que las variables estaban definidas como float.

El nuevo código es este:

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    'HTTP
    Dim request1 As HttpRequest
    Dim client1 As HttpClient
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
  
    'JSON
    Dim json As JSONParser
  
  
    Private ButtonGetBTC_LTC As Button
    Private EditTextOut As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("Layout1")

    client1.Initialize("client1") 'inicializa cliente HttpClient
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub ButtonGetBTC_LTC_Click
    Dim URL As String
    URL = "https://bittrex.com/api/v1.1/public/getticker?market=BTC-LTC"
    request1.InitializeGet(URL)
    client1.Execute(request1, 1)
End Sub

Sub client1_ResponseSuccess(Response As HttpResponse, TaskId As Int)
    Dim Success As String
    Dim Bid As Double
    Dim Ask As Double
    Dim Last As Double
  
    Dim m As Map
      
    'Dim texto As String  
    'texto = File.ReadString(File.DirAssets, "data.txt")
    'texto = "{""success"":True,""message"":"""",""result"":{""Bid"":0.01157113,""Ask"":0.01158113,""Last"":0.01158113}}"
  
    Dim json As JSONParser
    json.Initialize(Response.GetString("UTF8"))
  
    'Recuperamos el Objeto Raiz  
    m = json.NextObject
      
    Success = m.Get("success")    'Recuperamos 'success'
  
    m = m.Get("result")
      
    Bid  = m.get("Bid")  'Recuperamos 'Bid'
    Ask  = m.get("Ask")  'Recuperamos 'Ask'
    Last = m.get("Last") 'Recuperamos 'Last'

    'Mostramos los Datos
    EditTextOut.Text = "Success: " & Success & CRLF
    EditTextOut.Text = EditTextOut.Text & "Bid:  " & Bid & CRLF
    EditTextOut.Text = EditTextOut.Text & "Ask:  " & Ask & CRLF
    EditTextOut.Text = EditTextOut.Text & "Last: " & Last & CRLF
End Sub

Pero al ejecutarlo la aplicación se cierra inesperadamente.
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
en debug te va a salir el error exacto.

pero para mayor facilidad pon logs entre estas lineas:

B4X:
m = json.NextObject
     'aqui
    Success = m.Get("success")    'Recuperamos 'success'
    m = m.Get("result")
     'aqui
    Bid  = m.get("Bid")  'Recuperamos 'Bid'
    Ask  = m.get("Ask")  'Recuperamos 'Ask'
    Last = m.get("Last") 'Recuperamos 'Last'
    'Aqui
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Podria ser posible que no siempre te llegue el mismo valor JSON?

seria bueno que en Release (por que dices que en debug funciona bien)

pusieras un log aqui:

Response.GetString("UTF8")

pero bueno, mientras funcione, es la unica idea que se me ocurre.
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
creo que ya vi cual es el error!!

tu estas usando la libreria HTTP, cuando esta ya no esta mantenida y seguramente para las nuevas version de android falla, Erel ha explicado que es comun que algunas veces falle en release pero no en debug por que se toman diferentes lineas de ejecucion.

cambia tu libreria HTTP por la otra llamada OKHTTP, tambien te recomiendo usar OKHTTPUTILS. aunque para tu programa tal vez no es tan necesario.
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
mira lo que marca el IDE en relacion al GETSTRING

upload_2017-6-15_1-0-45.png

(este metodo esta depreciado yno funcionara adecuadamente en versiones de android 4+

Yo creo que lo mejor es que cambies a OKHTTP y despues que antes de checar si la pagina regreso lo que esperabamos.
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Top