The task is to check if there is an "s" field in the JSON, I've tried to do this as follows:
⍝ Example JSON I'm working with
JSON ← '{"e":"depthUpdate","E":1699599166770,"s":"BTCUSDT","U":40239636237,"u":40239636314,"b":[["36651.78000000","9.81839000"],["36584.34000000","0.00000000"],["36541.21000000","0.00055000"],["36459.23000000","0.00016000"]],"a":[["36651.79000000","0.47428000"],["36690.27000000","0.00000000"],["36690.96000000","0.00000000"],["36691.33000000", "1.40160000"]]}'
(⎕JSON JSON).⎕NL¯2 ⍝ Just checking the fields, there's definitely an 's' here
┌─┬─┬─┬─┬─┬─┬─┐
│E│U│a│b│e│s│u│
└─┴─┴─┴─┴─┴─┴─┘
1=⍴(⍸'s'∘≡¨(⎕JSON JSON).⎕NL¯2) ⍝ Finding
0
Although this example does work:
TMP ← 'id' 'result' 's'
TMP
┌──┬──────┬─┐
│id│result│s│
└──┴──────┴─┘
1=⍴(⍸'s'∘≡¨TMP)
1
But why? And how to fix it?
Perhaps there is a more direct way to check if a field exists in JSON?
The reason your code fails is
's'
being a scalar (0D array) while any name coming from JSON is a vector (1D array):However, you're actually implementing membership here, so you could use the primitive instead:
That said, you can ask about the nameclass of a name directly (and that's agnostic about scalar vs vector names). If the nameclass is 0, then the name is not defined. (If it is an object, it is 9, and any other array is 2.) Hence, the normal way to check if a name is defined, is to check for inequality to 0:
If you're using Dyalog 18.2+, you should use
⎕ATX
(full documentation) instead of⎕NC
as it gives more useful results in certain cases. While⎕ATX
can give you a lot of attibutes for a name, code 40 is the nameclass:Attempt this online!
In our case,
⎕NC
actually returns a vector, whereas⎕ATX
returns a more reasonable scalar (though they look the same using the default display form).