Quickly verify that variable contains JSON?

Anyone got any ideas on what's the quickest way (execution speed) to verify that a variable contains JSON?

Right now I'm just doing a simplistic check to make sure it starts with "{" or "[". If something fails after that, then I deal with it there. But it would be nice if I could do better than that, without costing me much time.

It's not a huge issue or anything, but I thought I'd see if anyone had any ideas.

I mean, I could dop into JXA to test it, but that's not very fast, execution-wise.

Hey Dan (@DanThomas):wave:

I am not good in writing Regular Expressions but I would definitely recommend going this route and check for all possible patterns youā€™d like to test.

This sounds as the quickest method to me.

Greetings from Germany :de:

Tobias

Thanks. Yeah, there are ways to use regex for this, but it's not all that reliable as far as I can tell - meaning you could get false negatives.

If someone wants to show me I'm wrong, though, I'd be happy to see it.

Ignore me (or by all means educate me!) if this is too primitive and uninformed, but my crack at it would be to check for at least one occurrence of a match for:

{"[a-zA-Z].*?":"[a-zA-Z].*?"}

So that's two strings beginning with a letter, enclosed in quotes, separated by a colon, and inside curly brackets.

1 Like

I also would consider to check after the specific pattern that you like to have as result.

Maybe a good way is including the Keys you expectā€¦ this is also what I would do ..

What I definitely would not do is trying to build something that is far too genericā€¦ that would then lead into false positives because I didnā€™t have made the decision to test for the exact thing I expected to have as a result.

Greetings from Germany :de:

Tobias

1 Like

Are you sure that execution speed is a reliable or efficient proxy for quality ?

I would personally reach straight for JSON.parse, and the messages which it can return, without wasting further time on profiling.

1 Like

Actually, I think I'm wasting my time doing this. I just need more robust error handling at the time of actually parsing the variable, and forget all this up-front checking.

I thought I was making things better, but it's actually making them worse.

2 Likes

A cheap and cheerful approach, for subsequent visitors to this thread who only need a simple result, is to evaluate an expression like:

%JSONValue%local_MaybeJSON%

which returns an empty string if the string value bound to the name local_MaybeJSON can not be parsed as JSON.

5 Likes

Rob youā€™re the man ā€¦ this is truly a powerful way ā€¦ and of course - pretty darn simple.

:man_facepalming:

Why havenā€™t I thought about that ?! - this makes me feel bad actuallyā€¦ I think sometimes I should give my ideas a little more time and a little more thinking :thinking:

Thanks :pray: for this wonderful suggestion. Why making things more complicated when they are as simple like that ?!

Greetings from Germany :de:

Tobias

Rob has a knack for coming up with stuff like this. Don't feel too bad - I've learned to just accept his brilliance and be happy he shares it with us.

I'm being dead serious, by the way. He's one of the good ones. Sometimes his solutions are beyond my comprehension, but that doesn't make them any less brilliant.

I total agree you on that, Dan ā€¦ I always take my hat (whenever Iā€™m wearing one) when I see new great stuff from Rob.

I mean these quite impressive coding skills ā€¦ the generics stuff he uses in his code every timeā€¦ whether itā€™s AppleScript or JXA ā€¦

Iā€™ve found someone who writes code in a way I am not able to fully understand and even am not able to learn ā€¦ I try my very best - but maybe itā€™s his experience against mineā€¦

Anyway - I have a lot of stuff from him as well and I truly love the stuff I have from him ā€¦

To Rob (@ComplexPoint) because he is going to read this, too: thanks again for so much good stuff - I take my hat ā€¦

Greetings from Germany :de:

Tobias

You know, I felt the same way until a few weeks ago, when I asked ChatGPT some questions about Rob's code. Specifically:

what does this do: const importedFrom = fNames =>
        // eslint-disable-next-line no-new-func
        fp => Function(
            [
                readFile(fp),
                return { ${fNames} };
            ]
                .join("\n")
        )();

ChatGPT understood exactly what it was doing, and helped me understand it. And then I went down a rabbit trail about Haskell, curried functions, things like that.

Bottom line - it turns out that it's not voodoo. Heh, who knew?

1 Like

Thatā€™s exactly what I was going through every time I tried again to get behind Robā€˜s code ā€¦ even without AI and I am not able to get it ā€¦ and I donā€™t know whyā€¦

:man_shrugging:

Sometimes I which I had code that would convert the stuff I donā€™t understand to something that I am able to understand like:

Code with Generics => Code without Generics

The better ā€¦ Code that even tells me how it is written in a different languageā€¦ like:

JXA with Generics => AppleScript without Generics

And done ā€¦

But reality is quite differentā€¦

Sigh :pensive:

Greetings from Germany :de:

Tobias

Everything you've said is how I've felt for years and years on this forum, when working with Rob's code, so please understand that I get it 100%.

I've always considered myself pretty smart, especially when it comes to programming, but Rob's stuff made me question myself over and over again.

So don't let it get to you, because I know I let it affect me and that didn't help, to say the least!

Here's an aside. I don't put Rob in the following category, but that may be just because I haven't met him face-to-face:

Many moons ago I worked with someone who was so smart, it was like he was beyond human. I told him once that I didn't understand relativity, and he commenced to try to explain it to me right then and there, and was utterly flummoxed when I didn't get it right away. It made me laugh.

Of course, in the intervening years, I have a better grasp of relativity, both general and special, but still - some people are just from another world.

:slight_smile:

Nothing clever here, just code which defines things, rather than ā€œdoingā€ things.

If you are used to the latter (imperative code) and try to work out what functional expressions ā€œdoā€, then then you may have a hard time :slight_smile:

We know what value 2 + 2 defines, but we may scratch our heads and lose some sleep if we start with the wrong question, and try to work out what it ā€œdoesā€.

We may tell ourselves:

ā€œFirst I do this, and then I do thatā€

but are we really little humunculi running around inside the machine during run-time evaluation of our code?

Or does thinking in those terms just add a redundant layer of confusion and complexity ?


@unlocked2412 is an experienced crafter of expressions which define solutions to problems.

Younger and more energetic than me too ā€“ and I think he does some teaching, if you are curious about functional composition, which is known, empirically, to:

  • Reduce the rate of bugs, and
  • increase the speed of code-writing.

then see if @unlocked2412 is available for some teaching.

( I donā€™t know what his rates are )

2 Likes

PS

Faster development, fewer bugs, much less wasted time ā€“ it all boils down to one simple trick:

No mutable names.

  • In Keyboard Maestro, once youā€™ve bound a name to a value, donā€™t change the meaning of that name. Never ā€˜updateā€™ an existing variable. New values always get new names
  • In JavaScript always use const ā€“ not let or var.

  1. Most bugs arise from mutable names,
  2. most of the rest arise from vagueness about the type of value that is bound to a given name.
1 Like

I am replying so that I can be corrected or otherwise further enlightened..!

I'm curious about what you mean by "defining". I think of functional code has acting upon a value to produce another value ā€“ the same as mathematical "transformation" but where the original is not (unless you explicitly arrange for it) changed or destroyed.

+ 2 is a function that can be applied to a value, x, which in the case of x = 2, results in 4. So we can define our function as something that adds 2 to a value (which is self-evident in terms of mathematical experience ā€“ if not mathematical definition!). We are not defining 4 however. It could be arrived at from an infinite number of other functions.

Nicely put, and a change from the "following a recipe for a cake" analogy. I think it's true to say that KM (especially when thinking of the Editor) most obviously lends itself to the "following a recipe" approach, but awareness of other paradigms can still be of great benefit.

That's really interesting, and something I shall think about.

Even in the syntax of functional languages, an immutable "variable" may be shown as if it were mutable ā€“ e.g. in a simple anonymous function in which x is replied to each of a set of values. In such cases, there is no chance of that x being confused with an x in another function. So bugs involving mutable names arise, I should imagine, from: (1) the programmer losing track of what the variable name currently refers to; (2) scope (which parts of the program can access the variable).

An argument for strong typing, alright. :slight_smile:

This discussion has made me curious about the situation that prompted the original question!

1 Like

I was just trying to do some pre-validation of a parameter. In the long run, I decided against it.

And I will just add that not everyone agrees with some of the points Rob brought up. I have no desire to "get into it" here, but I'll just say that if something sounds extreme, use your own mind and do your own research before you buy into it. And regardless of the particulars here, I'm sure Rob would agree with that.

1 Like

A function is a relationship between two sets.

For each value in the first set (the domain), a given function defines a specific corresponding value in the other set (the codomain).

There's no harm, of course, in introducing mnemonic metaphors of time, transformation, or agency here, but none of them are needed.

If we're looking for helpful metaphors or intuitions, it may be useful to think of a function as a value with a gap.

We know that sqrt n is a value drawn from the complex plane, but there's a gap in it called n

We don't know exactly which value in the codomain set is defined by sqrt n until we fill that gap with a specific value (drawn from the domain set).

sqrt 4 -> 2

sqrt -4 -> 2i


To put it another way, we know the type of sqrt n (the set from which it is drawn),
but only filling an argument slot with a value drawn from the domain set completes the picture,
defining a specific element in that codomain set.

1 Like

Related issues:

1 Like