Extract a LIST from JSON

Hello:

When I make a request with webapi, I receive a JSON file, which includes a list (maneuver) with several properties. Each query returns a different number of properties in that list (maneuver) and by not knowing how many properties are in that list, it is driving me crazy.
I would need to store in a list the latitude, longitude, and instruction property (in json maneuver list) to draw a polyline on a map.

The problem is that I don’t know the number of elements that the maneuver list (in json) has in each query that is made.

I include the json that I receive

JSON
{“response”:{“metaInfo”:{“timestamp”:“2020-08-30T09:05:47Z”,“mapVersion”:“8.30.112.151”,“moduleVersion”:“7.2.202034-7688”,“interfaceVersion”:“2.6.76”,“availableMapVersion”:[“8.30.112.151”]},“route”:[{“waypoint”:[{“linkId”:"+545865065",“mappedPosition”:{“latitude”:37.7868962,“longitude”:-3.6044061},“originalPosition”:{“latitude”:37.786893,“longitude”:-3.60433},“type”:“stopOver”,“spot”:0.0,“sideOfStreet”:“right”,“mappedRoadName”:“Calle Pintor Zabaleta”,“label”:“Calle Pintor Zabaleta”,“shapeIndex”:0,“source”:“user”},{“linkId”:"-539353117",“mappedPosition”:{“latitude”:38.0156565,“longitude”:-3.3724809},“originalPosition”:{“latitude”:38.01563,“longitude”:-3.3724741},“type”:“stopOver”,“spot”:0.0,“sideOfStreet”:“left”,“mappedRoadName”:“Calle Virgen de Guadalupe”,“label”:“Calle Virgen de Guadalupe”,“shapeIndex”:519,“source”:“user”}],“mode”:{“type”:“fastest”,“transportModes”:[“truck”],“trafficMode”:“disabled”,“feature”:[]},“leg”:[{“start”:{“linkId”:"+545865065",“mappedPosition”:{“latitude”:37.7868962,“longitude”:-3.6044061},“originalPosition”:{“latitude”:37.786893,“longitude”:-3.60433},“type”:“stopOver”,“spot”:0.0,“sideOfStreet”:“right”,“mappedRoadName”:“Calle Pintor Zabaleta”,“label”:“Calle Pintor Zabaleta”,“shapeIndex”:0,“source”:“user”},“end”:{“linkId”:"-539353117",“mappedPosition”:{“latitude”:38.0156565,“longitude”:-3.3724809},“originalPosition”:{“latitude”:38.01563,“longitude”:-3.3724741},“type”:“stopOver”,“spot”:0.0,“sideOfStreet”:“left”,“mappedRoadName”:“Calle Virgen de Guadalupe”,“label”:“Calle Virgen de Guadalupe”,“shapeIndex”:519,“source”:“user”},“length”:42855,“travelTime”:3337,“maneuver”:[{“position”:{“latitude”:37.7868962,“longitude”:-3.6044061},“instruction”:“Diríjase a <span class=“toward_street”>Avenida Rey Juan Carlos I por <span class=“street”>Calle Pintor Zabaleta. <span class=“distance-description”>Siga durante <span class=“length”>223 m.”,“travelTime”:73,“length”:223,“id”:“M1”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.7888918,“longitude”:-3.6046743},“instruction”:“Gire a la <span class=“direction”>izquierda en dirección a <span class=“sign”>Avenida San Juan de la Cruz. <span class=“distance-description”>Siga durante <span class=“length”>101 m.”,“travelTime”:39,“length”:101,“id”:“M2”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.788924,“longitude”:-3.6058116},“instruction”:“Continúe por <span class=“next-street”>Avenida San Juan de la Cruz. <span class=“distance-description”>Siga durante <span class=“length”>260 m.”,“travelTime”:68,“length”:260,“id”:“M3”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.788806,“longitude”:-3.608762},“instruction”:“Gire a la <span class=“direction”>derecha en dirección a <span class=“sign”><span lang=“es”>Baeza/<span lang=“es”>Úbeda/<span lang=“es”>Jaén. <span class=“distance-description”>Siga durante <span class=“length”>8 m.”,“travelTime”:8,“length”:8,“id”:“M4”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.7888703,“longitude”:-3.6088049},“instruction”:“Continúe en dirección a <span class=“sign”>A-320. <span class=“distance-description”>Siga durante <span class=“length”>15 m.”,“travelTime”:19,“length”:15,“id”:“M5”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.7889991,“longitude”:-3.6087728},“instruction”:“Tome la <span class=“exit”>4.ª salida de la rotonda en <span class=“number”>A-320 hacia <span class=“sign”><span lang=“es”>Jaén. <span class=“distance-description”>Siga durante <span class=“length”>1.3 km.”,“travelTime”:250,“length”:1321,“id”:“M6”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.789557,“longitude”:-3.622452},“instruction”:“Tome la <span class=“exit”>1.ª salida de la rotonda en <span class=“number”>A-316R8 hacia <span class=“sign”><span lang=“es”>A-316/<span lang=“es”>Jaén/<span lang=“es”>Úbeda. <span class=“distance-description”>Siga durante <span class=“length”>1.7 km.”,“travelTime”:147,“length”:1691,“id”:“M7”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:37.8041053,“longitude”:-3.6258638},“instruction”:“Tome la <span class=“exit”>3.ª salida de la rotonda en <span class=“number”>A-316 <span class=“next-street”>(Autovía del Olivar) hacia <span class=“sign”><span lang=“es”>Úbeda. <span class=“distance-description”>Siga durante <span class=“length”>32.8 km.”,“travelTime”:1876,“length”:32762,“id”:“M8”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0124378,“longitude”:-3.427552},“instruction”:“Tome la <span class=“exit”>4.ª salida de la rotonda en <span class=“number”>A-316R7 hacia <span class=“sign”><span lang=“es”>Torreperogil/<span lang=“es”>A-32/<span lang=“es”>Linares/<span lang=“es”>N-322. <span class=“distance-description”>Siga durante <span class=“length”>1.2 km.”,“travelTime”:141,“length”:1218,“id”:“M9”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0210853,“longitude”:-3.4207284},“instruction”:“Tome la <span class=“exit”>3.ª salida de la rotonda en <span class=“number”>A-32 hacia <span class=“sign”><span lang=“es”>Torreperogil/<span lang=“es”>Albacete. <span class=“distance-description”>Siga durante <span class=“length”>3.1 km.”,“travelTime”:197,“length”:3095,“id”:“M10”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0230594,“longitude”:-3.3872974},“instruction”:“Tome la salida <span class=“exit”>34 en dirección a <span class=“sign”><span lang=“es”>Úbeda Oeste. <span class=“distance-description”>Siga durante <span class=“length”>409 m.”,“travelTime”:63,“length”:409,“id”:“M11”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0210853,“longitude”:-3.3847547},“instruction”:“Tome la <span class=“exit”>3.ª salida de la rotonda en <span class=“number”>N-322 hacia <span class=“sign”><span lang=“es”>Úbeda Oeste. <span class=“distance-description”>Siga durante <span class=“length”>562 m.”,“travelTime”:144,“length”:562,“id”:“M12”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0174053,“longitude”:-3.3815467},“instruction”:“Tome la <span class=“exit”>4.ª salida de la rotonda Glorieta del Aceite en <span class=“next-street”>Avenida Don Cristóbal Cantero <span class=“number”>(N-322) hacia <span class=“sign”><span lang=“es”>Valencia/<span lang=“es”>Sabiote. <span class=“distance-description”>Siga durante <span class=“length”>835 m.”,“travelTime”:225,“length”:835,“id”:“M13”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0187893,“longitude”:-3.3726847},“instruction”:“Gire a la <span class=“direction”>derecha en <span class=“next-street”>Calle Virgen de Guadalupe. <span class=“distance-description”>Siga durante <span class=“length”>355 m.”,“travelTime”:87,“length”:355,“id”:“M14”,"_type":“PrivateTransportManeuverType”},{“position”:{“latitude”:38.0156565,“longitude”:-3.3724809},“instruction”:“Ha llegado a <span class=“street”>Calle Virgen de Guadalupe. Su destino está a la izquierda.”,“travelTime”:0,“length”:0,“id”:“M15”,"_type":“PrivateTransportManeuverType”}]}],“summary”:{“distance”:42855,“trafficTime”:3348,“baseTime”:3337,“flags”:[“motorway”,“builtUpArea”],“text”:“El viaje es de <span class=“length”>42.9 km y <span class=“time”>56 minutos.”,“travelTime”:3337,"_type":“RouteSummaryType”}}],“language”:“es-es”}}

Thanks.

I’ve had issues like this before. Typically what I do is use a for each block for the list in the JSON, then create a new list of just the latitude and longitude values. Something like the blocks below.
I was having some trouble getting thunkable to read in the JSON you included. First, THUNKABLE does not appear to be able to read the the directional quotation marks “”. Replacing those helped, but Thunkable was still having problems reading your JSON.

I THINK the problem is in the instruction property. It has some quotation markes within the Instruction property (for example span class=“street”). Can you change the returned data to not include the information property? If not, I’m not sure how to get Thunkable to load your JSON into a object. Perhaps other know how, but I don’t.

1 Like

Thanks for the reply.

The problem is that lat and long are inside an object called position inside maneuer. It may be that the problem is not with the quotes.

I attach the blocks where I try to get the information.

When I try to show a latitude for example in a label, the displayed text says “undefined”.

There are a few things going on.

First, without error trapping in thunkable, you will need some help debugging walking the JSON. I use a label set to multiline so I can see exactly where thunkable stops executing.

Next, you need to “nest” your loops. Again, because I can’t get your JSON to load, I am guessing at how the loops should be set up. But here is my guess.

For each level, first verify the property is in the object using the GetPropertiesOf block. If the property exists, I add a message to the label so I know at least that part worked.
Next set up a uniquely names loop of the list identified by the property name.

Keep nesting loops until you reach your final object (position).

This construct should find all position objects in all maneuvers for all legs for all routes in the response object. Or at least something like this. You will need to debug it to see where my errors are.

Best of luck!

1 Like

Pedro,

With the Web_API URL you sent, I was able to get to the latitude and longitude values and use them to build a new list. Notice how at each step I checked. the value. My experience has taught me that when working with complex JSON in Thunkable, do not try to build all of the blocks up front. Build one loop at a time, and check the results as you go. I’ve included a screenshot as well as a link to the project (with the URL removed).

https://x.thunkable.com/copy/633fe638c21cbbdbfd6a695eddadb54b

1 Like

:mechanical_arm:

2 Likes

Thank you very much for your answer.

That is the solution.

Very grateful for your help.

@drted

Typically, a JSON response from a single service has a specific and unchangeable data structure, because otherwise users will simply not be able to use it if it changes the property names and structure depending on the request. Even if we assume that the data structure is changing, this is not a reason to search for nodes manually using a heap of IF blocks. Let’s assume that the JSON data structure has a depth of 100. You will have to manually use 100 units the IF?

If you send me 2 different versions of the JSON response (so that I can see what changes there are) in the correct form, I will show you simple blocks for getting data.

Sent.

actech is correct. All of the ifs, loops, and label updates are not strictly necessary if the JSON is known and reliable. This is just the way I debug my code. I’m also kinda weird in that if an external service changes, I like my apps to keep running vs. completely shutting down as Thunkable does if an object property does not exist.

If you are confident that there will ALWAYS be exactly one response object, one object in the route list, one object in the leg list, and one list named maneuver, that will always have a position object with latitude and longitude properties, there are MUCH simplier way to iterate through the maneuver list. The solution below uses a helper function GetProperty which recursively walks down the JSON herarchy. Each item in the KeyPath list represents a level of the hierarchy, either the name of the object or the position in a list (0 being the first item in the list).

If the response structure of the service changes, then you need to hit the head of the person who did it ))

You are right to check the existence and correctness of data before using it. But it is better not to do it manually. If we have to check everything manually when using a computer, then why do we need a computer?

If you give me a working JSON structure in which to define a list or text, then I can think about how to do an automatic type check. Finally, you can send the result to Javascript and find out the data type.

If you are interested, you can give me your universal algorithm for parsing JSON and I will try to break it by creating a JSON that will break it during analysis.

So true on all of your points!

I WISH I had a bombproof universal algorithm! It always comes down to the number of nines you want.