Parsing query string in Node to allow logical operators - json

I would like something similar to what node-odata offers, but I do not want to wrap it around my database (I am using Cassandra and already have an Express app set up with routes, etc).
Currently, I grab data from the database (which will ultimately return a JSON object to the user) and then using the values passed in the query string I modify the results with JavaScript and pass the modified JSON object on through to the user.
I cannot pass in a query string like this http://localhost:3001/getSomeData?name=jim&age=21||eyeColor=red which includes logical operators in the query string, and would grab all data and filter it where the name is "jim", the age is "21" OR eyeColor is "red". So this would give me all Jims that have either eyeColor red and/or age of 21. If I used this age=21&&eyeColor=red I would expect to get all Jims that have BOTH eye color of red and are 21 years old.
I was thinking of using a custom query string that can be passed in (i.e. inclusive=age&inclusive=eyeColor appended at the end of the query string) and in Node, I would modify the filter results to treat these properties (age and eyeColor) as if they were passed in with the || OR operator). However, this is quite verbose, and I was hoping there was a library or another simpler implementation out there that solves this problem, or somehow lets me pass in simple logical operators into the query string.

I ended up using this library to achieve what I wanted: https://www.npmjs.com/package/jspath
It's well document and worked perfectly for my situation.

npm i querystringify //or
https://cdnjs.cloudflare.com/ajax/libs/qs/6.7.0/qs.min.js
//it will will return an object
const myObject = Qs.parse(location.search, {ignoreQueryPrefix: true});
//you can use object destructuring.
const {age,eyeColor}=Qs.parse(location.search, {ignoreQueryPrefix: true})
By default, parsing will include "?" too.
{ignoreQueryPrefix: true} this option will omit "?".

Related

Supporting JSON paths in BigQuery

I was wondering if BigQuery has any additional support to JSON paths, as it seems like this is such a common way to work with nested data in BigQuery. For example, as a few years ago it seemed like the answer was: What JsonPath expressions are supported in BigQuery?, i.e., "Use a UDF".
However, it seems like using a path within an array, such as:
`$..Job'
Is such a common operation given BigQuery's repeated field, that about 70% of the times I've tried to use BigQuery's JSON_EXTRACT, I run into the limitation of having to iterate down an array.
Is this ability supported yet in BigQuery, or are there plans to support it, without having to do a UDF? As nice as something like the following works:
CREATE TEMPORARY FUNCTION CUSTOM_JSON_EXTRACT(json STRING, json_path STRING)
RETURNS STRING
LANGUAGE js AS """
try { var parsed = JSON.parse(json);
return JSON.stringify(jsonPath(parsed, json_path));
} catch (e) { return null }
"""
OPTIONS (
library="gs://xx-bq/jsonpath-0.8.0.js"
);
SELECT CUSTOM_JSON_EXTRACT(to_json_string(Occupation), '$..Job'), to_json_string(MovieInfo), json_extract(MovieInfo, '$.Platform') FROM `xx-163219.bqtesting.xx` LIMIT 1000
It ends up taking anywhere between 4-6x longer than a normal JSON_EXTRACT function (2s vs. about 10s). Or, is there something that I'm missing with what you're able to do with JSON objects in BQ?
Currently, the support for JSONPath on BigQuery includes and is limited to $, ., and [], where the latter can be either a child operator or a subscript (array) operator.
Other syntax elements from JSONPath are not supported, but for future reference, there's a public feature request to support complete JSONPath syntax.

clojure.data.json/write-str: specifying a key function for placing values into aggregate arrays

Suppose I have a simple map, example-map:
(def example-map {"s" {"f" "g"}
"m" {"r" "q"}})
I can use clojure.data.json/write-str to JSON-ify this map as such:
(clojure.data.json/write-str example-map) =>
"{\"s\":{\"f\":\"g\"},\"m\":{\"r\":\"q\"}}"
I'd like to conditionally place some of the values into lists according to the value of their keys.
write-str provides an optional :key-fn, which applies some function to key value pairs. For example, the desired function might specify that all values associated with entries that match "s" are placed in lists.
(clojure.data.json/write-str example-map :key-function desired-function) =>
"{\"s\":[{\"f\":\"g\"}],\"m\":{\"r\":\"q\"}}"
Does anyone know how to specify such a key function that checks for membership of a key in a set and places the values associated with members into an array rendered in the output JSON?
Like your previous question, this is not a job for the JSON parser. You don't need to rely on write-time features of your JSON library to adjust the shape of your JSON maps. Instead, you have a fully functional Turing complete language at your disposal: Clojure! If the maps don't already look the way you want them to be output, then write a function that takes one Clojure map as input and produces a different one as output; then ask your JSON library to write the output map, without any special rules for fiddling with the output.
Now, as it happens this particular JSON library does provide an option named value-fn (not key-function as you claim) to let you modify a value in a map based on its key. So you could use that, in which case you simply need to write a function with a signature like:
(fn [k v]
(...compute new value...))
There are many ways you could write such a function, but they are all entirely divorced from your JSON parser. If you need help writing it, mention some specific things you need help with, so you can get a clear explanation for the part of the process that is actually giving you trouble.

Which one to use Value vs std::string in cocos2d-x V3 C++?

According to http://www.cocos2d-x.org/wiki/Value,
Value can handle strings as well as int, float, bool, etc.
I'm confused when I have to make a choice between using
std::string
or
Value
In what circumstances should I use Value over std::string, and vice versa??
I think you have misunderstood the Value object. As written in the documentation you linked to:
cocos2d::Value is a wrapper class for many primitives ([...] and std::string) plus [...]
So really Value is an object that wraps a bunch of other types of variables, which allows cocos2d-x to have loosely-typed structures like the ValueMap (a hash of strings to Values - where each Value can be a different type of object) and ValueVector (a list of Values).
For example, if you wanted to have a configuration hash with keys that are all strings, but with a bunch of different values - in vanilla C++, you would have to create a separate data structure for each type of value you want to save, but with Value you can just do:
unordered_map<std::string, cocos2d::Value> configuration;
configuration["numEnemies"] = Value(10);
configuration["gameTitle"] = Value("Super Mega Raiders");
It's just a mechanism to create some loose typing in C++ which is a strongly-typed language.
You can save a string in a Value with something like this:
std::string name = "Vidur";
Value nameVal = Value(name);
And then later retrieve it with:
std::string retrievedName = nameVal.asString();
If you attempt to parse a Value as the wrong type, it will throw an error in runtime, since this is isn't something that the compiler can figure out.
Do let me know if you have any questions.

Accessing nested list items in an interpolated string using dot notation in Scala

I'm trying to pass a value via JSON that I am having trouble accessing. We have a data structure (that was obviously not built by me otherwise I would likely understand it) that looks something like this when sent to the browser:
{Foo(Bar(List(Baz(List(G3),w))),G3,None)}
This is sent via a JSON write method, but the originating Scala line looks like:
val hint = Some(s"{$question}") where $question is of type Foo.
I've tried using dot notation to access the list items in ways that I thought would work:
val hint = Some(s"{$question.Bar.Baz})"
val hint = Some(s"{$question.Bar(0).Baz(0)"})
It's the deepest G3 I wanted to strip out and send, but instead the JSON object comes through looking like:
{Foo(Bar(List(Baz(List(G3),w))),G3,None)}.Bar.Baz or
{Foo(Bar(List(Baz(List(G3),w))),G3,None)}.Bar(0).Baz(0)
I must be fundamentally missing something about the data structures involved here.
I think you're just using the wrong syntax. The $ needs to come before the {} and the {} is necessary for any expression more complicated than just a variable name:
s"${question.bar(0).baz(0)}"

Use a period in a field name in a Matlab struct

I'm using webwrite to post to an api. One of the field names in the json object I'm trying to setup for posting is odata.metadata. I'm making a struct that looks like this for the json object:
json = struct('odata.metadata', metadata, 'odata.type', type, 'Name', name,);
But I get an error
Error using struct
Invalid field name "odata.metadata"
Here's the json object I'm trying to use in Matlab. All strings for simplicity:
{
"odata.metadata": "https://website.com#Element",
"odata.type": "Blah.Blah.This.That",
"Name": "My Object"
}
Is there a way to submit this json object or is it a lost cause?
Field names are not allowed to have dots in them. The reason why is because this will be confused with accessing another nested structure within the structure itself.
For example, doing json.odata.metadata would be interpreted as json being a struct with a member whose field name is odata where odata has another member whose field name is metadata. This would not be interpreted as a member with the combined field name as odata.metadata. You're going to have to rename the field to something else or change the convention of your field name slightly.
Usually, the convention is to replace dots with underscores. An automated way to take care of this if you're not willing to manually rename the field names yourself is to use a function called matlab.lang.makeValidName that takes in a string and converts it into a valid field name. This function was introduced in R2014a. For older versions, it's called genvarname.
For example:
>> matlab.lang.makeValidName('odata.metadata')
ans =
odata_metadata
As such, either replace all dots with _ to ensure no ambiguities or use matlab.lang.makeValidName or genvarname to take care of this for you.
I would suggest using a a containers.Map instead of a struct to store your data, and then creating your JSON string by iterating over the Map filednames and appending them along with the data to your JSON.
Here's a quick demonstration of what I mean:
%// Prepare the Map and the Data:
metadata = 'https://website.com#Element';
type = 'Blah.Blah.This.That';
name = 'My Object';
example_map = containers.Map({'odata.metadata','odata.type','Name'},...
{metadata,type,name});
%// Convert to JSON:
JSONstr = '{'; %// Initialization
map_keys = keys(example_map);
map_vals = values(example_map);
for ind1 = 1:example_map.Count
JSONstr = [JSONstr '"' map_keys{ind1} '":"' map_vals{ind1} '",'];
end
JSONstr =[JSONstr(1:end-1) '}']; %// Finalization (get rid of the last ',' and close)
Which results in a valid JSON string.
Obviously if your values aren't strings you'll need to convert them using num2str etc.
Another alternative you might want to consider is the JSONlab FEX submission. I saw that its savejson.m is able to accept cell arrays - which can hold any string you like.
Other alternatives may include any of the numerous Java or python JSON libraries which you can call from MATLAB.
I probably shouldn't add this as an answer - but you can have '.' in a struct fieldname...
Before I go further - I do not advocate this and it will almost certainly cause bugs and a lot of trouble down the road... #rayryeng method is a better approach
If your struct is created by a mex function which creates a field that contains a "." -> then you will get what your after.
To create your own test see the Mathworks example and modify accordingly.
(I wont put the full code here to discourage the practice).
If you update the char example and compile to test_mex you get:
>> obj = test_mex
obj =
Doublestuff: [1x100 double]
odata.metadata: 'This is my char'
Note: You can only access your custom field in Matlab using dynamic fieldnames:
obj.('odata.metadata')
You need to use a mex capability to update it...