Empty array (zero size)

I get some JSON data:

{var => [{par1 => 33, par2 => null}]}

However, sometimes data comes:
{var => []}

How can I recognize that data["var"] matches the last option?

if (data["var"] instanceof Lang.Array) - false

if (data["var"].equals([])) - false

Sys.println(data["var"]) - method

  • You can use the .size() function to return the size of the array.  I don't know if the following will return 1 or 0, but should get you looking in the right direction.

    {var => []}
    println(var.size());

  • Thank! I have tried this.

    At first to no avail.

     

    Received Data: {val => [{par1 => 33, par2 => null}]}
    println (data["val"].size ()); // - 0
    Received Data:{val => []}
    println (data["val"].size ()); // - 0

    But

    Received Data: {val => [{par1 => 33, par2 => null}]}
    var temp = data["val"];
    println (temp.size ()); // - 1
    .... 
    Received Data: {val => []}
    var temp = data["val"];
    println (temp.size ()); // - 0

    Strange, isn't it?

  • I think the issue you are facing is you are trying to reference a dictionary with 2 keys, inside a single element array that is included inside a single key dictionary.  I do very little at the moment with both data types.  I think you need to look at something like.

    data.get(val).size();

    in order to check the specific array within the larger dictionary.

  • Interesting. I’ll take a peek at this tomorrow.

    Given that this is reporting the type of data[“var”] is method, it seems like a bug. If making a temporary works as you’ve shown, then that seems like a reasonable workaround for the time being.

  • I've tried to reproduce this in every way we can access something that is JSON-like (a MonkeyC dict, a JSON resource, and downloading a JSON document via makeWebRequest). I cannot reproduce the problem.

    Here is my test code:

    using Toybox.Application;
    using Toybox.System;
    using Toybox.WatchUi;
    using Toybox.Graphics;
    using Toybox.System;
    using Toybox.Lang;
    using Toybox.Communications;
    
    
    class SimpleDelegate extends WatchUi.BehaviorDelegate
    {	
    	function initialize() {
    		BehaviorDelegate.initialize();
    		
    		verify({"val" => [{"par1" => 33, "par2" => null}]});
    		verify({"val" => []});
    
    		verify(WatchUi.loadResource(Rez.JsonData.test1));
    		verify(WatchUi.loadResource(Rez.JsonData.test2));
    	}
    	
    	hidden const _urls = [
    		"http://localhost:8080/test1.json",
    		"http://localhost:8080/test2.json",
    	];
    	
    	hidden var _index = 0;
    	
    	function onSelect() {
    	
    		var url = _urls[_index];
    		_index = (_index + 1) % _urls.size();
    
            var params = {
            };
    
            var options = {
            };
    
            Communications.makeWebRequest(url, params, options, method(:onWebResponse));
    
    		return true;
    	}
    	
    	function verify(data) {
    		System.println(data);
    			
    		if (data instanceof Lang.Dictionary) {
    			System.println("`data` is a dict.");
    			
    			if (data["val"] instanceof Lang.Array) {
    				System.println("`data['val']` is an array.");
    				System.println("`data['val'].size()` is " + data["val"].size());
    			}
    			else {
    				System.println("`data['val']` is not an array.");
    			}
    		}
    		else {
    			System.println("`data` is not a dict!");
    		}
    	}
    	
    	function onWebResponse(code, data) {
    		System.println(code);
    		
    		verify(data);		
    	}
    }
    
    class SimpleApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
        
        function getInitialView() {
            return [ new WatchUi.View(), new SimpleDelegate() ];
        }
    }
    

    Here is the definitions for the JSON resources referenced by that code:

    <resources>
        <jsonData id="test1">
            {"val": [{"par1": 33, "par2": null}]}
        </jsonData>
        <jsonData id="test2">
            {"val": []}
        </jsonData>
    </resources>

    I created two text files on my desktop, test1.json and test2.json. Here is the content of each of those files displayed in a terminal.

    C:\Users\vitek\Desktop>type test1.json
    {
        "val": [
            {
                "par1": 33,
                "par2": null
            }
        ]
    }
    C:\Users\vitek\Desktop>type test2.json
    {
        "val": []
    }
    C:\Users\vitek\Desktop>

    I started up the simple HTTP server that is built into python like this:

    C:\Users\vitek\Desktop>py -2 -m SimpleHTTPServer 8080
    Serving HTTP on 0.0.0.0 port 8080 ...

    I built the app and ran it under a fenix5x device configuration. Before pressing any buttons, I verified that Settings > Connection Type > BLE > Connected was checked. I verified that Settings > Connection Type > WiFi > Not Initialized was not checked (that step probably isn't necessary, but it forces the simulator to behave like you'd see with an actual device connected over BLE). I then made sure that Settings > Use Device HTTPS Requirements was not checked (because the SimpleHTTPServer I'm running isn't configured for SSL).

    Once I had all that setup, I clicked the Enter button (the top-right button on the fenix5x I'm simulating) once, looked at the result, and clicked the Enter button again.

    Here is the output:

    {val=>[{par2=>null, par1=>33}]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 1
    {val=>[]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 0
    {val=>[{par2=>null, par1=>33}]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 1
    {val=>[]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 0
    200
    {val=>[{par2=>null, par1=>33}]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 1
    200
    {val=>[]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 0
    

    Given that I can't reproduce the problem you're seeing, it might be a good idea if you could provide a test case.

  • Thanks for your efforts!
    The fact is that I analyzed in the background in the WF application in the body of onWebResponse the received data  directly without calling Verify.

  • I still can't reproduce, even if I do the makeWebRequest call in the background and process the result in the onWebResponse function directly.

    using Toybox.Application;
    using Toybox.System;
    using Toybox.WatchUi;
    using Toybox.Graphics;
    using Toybox.System;
    using Toybox.Lang;
    using Toybox.Communications;
    
    class SimpleDelegate extends WatchUi.BehaviorDelegate {
    
    	hidden var _app;
    
    	function initialize(app) {
    		BehaviorDelegate.initialize();
    		_app = app;
    	}
    	
    	function onSelect() {
    		_app.onAppUpdate();
    		return true;
    	}
    }
    
    class SimpleApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
        
        function getInitialView() {
            return [ new WatchUi.View(), new SimpleDelegate(self) ];
        }
        
        (:background)
        function onAppUpdate() {
            fetchJson("http://localhost:8080/test1.json");
            fetchJson("http://localhost:8080/test2.json");
        }
        
        (:background)
        function getServiceDelegate() {
            return [ new System.ServiceDelegate() ];
        }
        
        function fetchJson(url) {
            var params = {
            };
    
            var options = {
            };
    
            Communications.makeWebRequest(url, params, options, method(:onWebResponse));
        }
        
        function onWebResponse(code, data) {
            System.println(code);
            System.println(data);
                
            if (data instanceof Lang.Dictionary) {
                System.println("`data` is a dict.");
                
                if (data["val"] instanceof Lang.Array) {
                    System.println("`data['val']` is an array.");
                    System.println("`data['val'].size()` is " + data["val"].size());
                }
                else {
                    System.println("`data['val']` is not an array.");
                }
            }
            else {
                System.println("`data` is not a dict!");
            }
        }
    }
    

    Here is the output of that program:

    Background: 200
    Background: {val=>[]}
    Background: `data` is a dict.
    Background: `data['val']` is an array.
    Background: `data['val'].size()` is 0
    Background: 200
    Background: {val=>[{par2=>null, par1=>33}]}
    Background: `data` is a dict.
    Background: `data['val']` is an array.
    Background: `data['val'].size()` is 1
    200
    {val=>[]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 0
    200
    {val=>[{par2=>null, par1=>33}]}
    `data` is a dict.
    `data['val']` is an array.
    `data['val'].size()` is 1
    

    I've spent a good part of my day trying to reproduce this. It would be greatly appreciated if you could provide a test case that demonstrates the problem.

  • Ok. I get data from someone else's server. As soon as the problematic data arrives, I will write here.

  • Even if you could provide the URL that you're hitting, that would be better than what I've got.

  • I have to apologize ... I never managed to reproduce the described situation. Maybe I messed up something.
    However, data["val"].size() solved the problem.

    Thanks to all!
    Special thanks to

    I use URL

    "https://avwx.rest/api/metar/"+lat+"%2C"+lon+"?options=&airport=true"