$.store.book[?@.price < 10].title
Python: [x['title'] for x in data['store']['book'] if x['price'] < 10]
Javascript: data.store.book.filter(x=>x.price < 10).map(x=>x.title) $.store.book[?@.price < 10].title
Python: [x['title'] for x in data['store']['book'] if x['price'] < 10]
Javascript: data.store.book.filter(x=>x.price < 10).map(x=>x.title)Can you write examples in Python and Javascript where you'd extract those titles from an arbitrary JSON structure? ;-)
$..book[?@.price<10].title
Yeah, I don't think javascript has that function in the standard library. Writing one is not super complicated, but having to put that into every file (or importing it) is not ideal. find_key = (data, key) => {
if(data instanceof Array){
return data.map(x=>find_key(x, key)).flat()
}
if(data instanceof Object){
let res = Object.keys(data).map(x=>find_key(data[x], key))
if(data.hasOwnProperty(key)){
res.push(data[key])
}
return res.flat()
}
return []
}
find_key(data, "book").filter(x=>x.price < 10).map(x=>x.title)How would one use JSONPath to extract all book titles from an arbitrary JSON structure?
Also, when might that use case apply? I can't think of when I've ever needed to do something like this, but I'm interested in learning. :)
You wouldnt use json path as replacement to any language. It might be marginally useful in configurations or passing queries between different services. But the complex syntax limits it in both cases, because you cannot easily automatically modify the query. In the case of configs it would be great to analyze hundreds of configs on different systems and change them automaticaly, same with queries exchanged between services which might even get stored in a database.
I do not understand why domain languages aren't designed with limited syntax in mind. In the style of lisp for instance. Because actually being able to programatically work with the language is a massive advantage that imo far outweights your own frustration with typing a paranthesis or two extra.
[
for book in input.store.book:
if book.price < 10:
book.title
] data['store']['book'].filter(lambda x: x.price < 10).map(lambda x: x.title)
Yeah, not nearly as good. The syntax sugar of a.b instead of a['b'] and arrow functions instead of lambda really does make a pretty big difference. data.store.book.filter(_.price < 10).map(_.title)
Every language should just adapt it. data.store.book.filter(_.price < 10).map(_.title)
would be written as data.store.book.grep(*.price < 10).map(*.title) let possibleNow =
people
|> List.distinctBy _.Name
|> List.groupBy _.Age
|> List.map snd
|> List.map _.Head.Name
|> List.sortBy _.ToString() filter((x) => x.price < 10)
but why can’t we just write filter(x.price < 10)
and add a rule to the JS engine that says “when you encounter a ‘syntax error: undeclared identifier x’, rewrite the code to add `(x) => ` in front of where the syntax error occurred, if and only if this rewrite prevents the syntax error”.You might protest that reacting to syntax errors by inserting extra code and checking if the errors go away is an insane strategy, but I would note that JavaScript is actually a semicolon-terminated language in which most developers never write a semicolon, and the JavaScript engine is already using this insane strategy on nearly every line of modern JS to insert a semicolon whenever it encounters a syntax error, so it’s obviously practical.
filter(_.price < 10)
That may not work because plain underscore is already a valid identifier but another placeholder could potentially be used and no need for the parser backtracking / function insertion (which I don't like the idea of, there may be cases where an undeclared identifier was a bug and it shouldn't be turned into a function) grep(*.price < 10)
This is referred to as "Whatever-currying": https://docs.raku.org/type/Whatever*I think that the automatic semicolon insertion is a bad feature of JavaScript.
val numbers = listOf(20, 19, 7, 12)
val multiplied = numbers.map { 3 * it }
// [ 60, 57, 21, 36 ] data.store.book.grep(*.price < 10).map(*.title)
Although personally I would write that as: data.store.book.map: { .title if .price < 10 }
which combines the filter / map into a single operation.As an aside the js example above could be simplified to a reduce().
store.book[][$$.price lt 10].title
or the more verbose: for $book in store.book[]
where $book.price lt 10
return $book.titleI think you missed my point.
In realistic code you'd be using string interpolation to put the number 10 into this query language, and worrying about injection vulnerabilities while you did it.
Or even calling another arbitrary function to do the filtering. Which this query language can't handle at all.