Here's my situation, I have a JSON that looks somewhat like this:
{
"items": [{
"type": "condition",
"data": {
"type": "comparison",
"value1": {
"source": "MyType1",
"component": "Attribute1"
},
"value2": {
"source": "MyType2",
"component": "Attribute2"
},
"operator": "gt"
}
},
{
"type": "then",
"data": {
"result": "failed",
"message": "value1 is too high"
}
}
]
}
and would want it to translate to:
if (MyType1.Attribute1 > MyType2.Attribute2) {
result = "failed";
console.log("value1 is too high");
}
Now my problem is, I don't know how I would translate the entries of value1 and value2 to actual code, or rather, how I could access the Object MyType1(maybe through something like getAttribute("MyType1")).
Since I am going to have a whole bunch of sources which each have different components, I cant really write a huge dictionary. Or I would like to avoid it.
The goal is to allow creating if - then - statements via some interactive UI, and I figured it'd be best to save that code as .json files. (Think rule management system).
So, TL,DR, How would I access a Class Attribute this.MyType, if I only have a String MyType to go from? And how would I access the value this.MyType.MyValue, if I get another String MyValue?
Thanks in advance.
Edit:
I'd really like to avoid using eval, for obvious reasons. And if I have to - I guess I would need to create Dictionaries for possible JSON Values, to validate the input?
You need some kind of parser. At first we need some way to store variables and maybe flags:
const variables = {};
var in = false;
Then we go through the code and execute it:
for(const command of items){
switch( command.type ){
case "condition":
//...
case "then":
//...
}
}
To access a variable we can simply do
var current = variables[ identifier ];
To store its the other way round:
variables[ identifier ] = current;
Related
I'm building a little web-app to practice and learn Vue.js and working with APIs.
For a particular problem I want to solve, I would like to return the object that has the matching uuid that I request.
With my current knowledge, I understand I can do this by implementing some sorts and loops logic.
However I'm still new with JS, Vue.js, so I'm not sure if there is a better way to approach this.
Is there a built in function, or some form of "best practice" to approach this?
methods: {
fetchItem(row) {
// row.target_uuid -- this is the UUID I want
// this.$props.todoItems; -- this contains the json objects
// return this.$props.todoItems[i] where this.$props.todoItems[i]['uuid'] == row.target_uuid
},
This is a snippet of my $props.todoItems for context
[
{
"title": "Install Maris",
"uuid": "9ec9ea6b-0efc-4f6a-be2e-143be5748d3a",
"field_completed": "False"
},
{
"title": "Figure out why VS Code sucks",
"uuid": "85120da5-ee59-4947-a40f-648699365c73",
"field_completed": "False"
},
{
"title": "Start designing portfolio",
"uuid": "243c1960-7ade-4a68-9a74-0ccc4afa3e36",
"field_completed": "False"
},
{
"title": "Meal Prep",
"uuid": "85b64b18-9110-44d8-bd2d-8f818b0a810f",
"field_completed": "False"
},
{
"title": "Sharpen knives",
"uuid": "8a7ac5f6-8180-4f20-b886-628fd3bcfc85",
"field_completed": "False"
},
{
"title": "Set up SSH keys",
"uuid": "f879c441-8c05-4f24-9226-125c62576297",
"field_completed": "False"
}
]
If you know you're looking for exactly one item (or the first item that matches) you should take a closer look at the Array.find() method provided by JS. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
Also take a look at all the other methods the Array prototype provides, most of them are fairly descriptive and solve most of the basic problems you'll encounter.
To use this in your Vue app you can either have a method that returns your todo based on a provided uid like this
todoByUid(uidToFind) {
return this.todos.find(todo => todo.uid == uidToFind)
}
If you only care about a currently selected item a computed value as Jacob mentioned is the way to go:
computed() {
selectedTodo() {
return this.todos.find(todo => todo.uid == this.selectedUid)
}
}
(Sorry if the title doesn't make much sense, I had no idea how to word the question right and that was the best way I could think of)
So I have an API (the steam API) that returns something like this:
{
"playerstats": {
"steamID": "76561197962837077",
"gameName": "ValveTestApp260",
"stats": [
{
"name": "total_kills",
"value": 3255
},
{
"name": "total_deaths",
"value": 4816
},
...
{
"name": "total_shots_hit",
"value": 3642
}
{
"name": "total_shots_fired",
"value": 4572
}
...
],
}
}
So I want to get the value for total_shots_hit and total_shots_fired, but it's in a different order for different people so I was wondering how I would get the value depending on the name in each of the sections? The way I'm doing it right now is by doing statsResponse.playerstats.stats[39].value, but it's not in the 39th spot for everyone, so I was wondering how I would get it? I'm using JavaScript/jQuery if that helps at all.
Any help is appreciated :)
EDIT: Figured out how to do it, I used a for loop to go through every response until it found the item I wanted, then used that number to find the same value
You can use Array.find() to find an object in an array by one of its properties.
var o = stats.find(function(item) {
return item.name === 'total_shots_hit';
}
console.log(o.value) // value property, e.g. 3642
Can you guys teach me on how to use jsoniq to display both of the book name which is robin cruose and tom jones? i've gone through some research but no matter how i do, it's always wrong.
{
"books": {
"reader": {
"Read": {
"book": {
"name": "Robinson Crusoe",
"author": "Daniel Defoe"
}
},
"HaventRead": {
"book": {
"name": " Tom Jones",
"author": "Henry Fielding "
}
},
"_type": "Ken Rawing"
}
}
}
This is how i did in zorba.io and it got lots of error, i am very sure the way i did is totally wrong. Please teach me
for $reader in collection("books"),
$read in collection("books"),
$book in collection ("books")
where $reader.type eq "Ken Rawing"
return $book
Getting some leaf values from a JSON document is done with the navigation syntax, which is the . notation.
It doesn't need a for clause, as iteration is implicit with the ..
Assuming the object is stored in the variable $content, $content.books.reader navigates to the object with the fields Read and HaventRead. Calling jnlib:values() then gets the two objects in there, and then one continues all the way to the name with .book.name.
The query is like so (most of it is actually the input document itself, which is typically stored in a file or a data store instead):
jsoniq version "1.0";
import module namespace jnlib = "http://jsoniq.org/function-library";
(: That's the input document, stored in a global variable :)
declare variable $content := {
"books": {
"reader": {
"Read": {
"book": {
"name": "Robinson Crusoe",
"author": "Daniel Defoe"
}
},
"HaventRead": {
"book": {
"name": " Tom Jones",
"author": "Henry Fielding "
}
},
"_type": "Ken Rawing"
}
}
};
(: That's the query :)
jnlib:values($content.books.reader).book.name
Mind the jsoniq version="1.0";, which activates the native JSONiq parser (the default parser on try.zorba.io is XQuery).
It can also be tested in zorba.io
Note
JSONiq also exists as an extension to XQuery, in which case navigation is done with function calls, as the . is a valid character in XML names. However, it is not recommended to use this unless you have XML to deal with as well.
jnlib:values($content("books")("reader"))("book")("name")
The image shows the structure of my database.
I want to print 1, 2 ... (so on) i.e. the parent element names alone. But couldn't understand how to do that.
The Firebase Database is essentially one JSON object.
This object is in a tree structure. If you read from one location in the tree, you'll get each piece of data underneath it.
Take a look at this sample database.
{
"items": {
"1": {
"title": "Hi"
},
"2": {
"title": "Bye"
}
}
}
There is no way with the JavaScript SDK or AngularFire, to only read the parent keys of 1 and 2 under "items".
If you only want to read the parent keys, you'll need to create an index for them in the Firebase database.
{
"items": {
"1": {
"title": "Hi"
},
"2": {
"title": "Bye"
}
},
"itemKeys": {
"1": "Hi",
"2": "Bye"
}
}
Now you can create a reference at the itemKeys location and pass that to a $firebaseArray() or $firebaseObject().
var ref = new Firebase('<my-firebase-app>.firebaseio.com/itemKeys');
var syncArray = $firebaseArray(ref);
If you're concerned with keeping two separate data structures consistent, check out the client-side fan-out feature.
shallow=true
If you are using REST API add this to the end of your request url. Like this
https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true
I am on a Dojo app, is there any special JS parser which enables me default values within JSON data ?
Example, I'd like to set "maxHeadingLength" in item[1] to the value in item[0].
{
items:[
{
"class": "pmedia.types.PMPlatformRenderConfiguration",
"listItemHeight": "70",
"listItemIconHeight": "60",
"maxDesktopItemsWithBannerP": "9",
"maxDesktopItemsWithBannerL": "9",
"platform": "Default",
"maxHeadingLength":
{
P:300,
L:400
}
},
{
"class": "pmedia.types.PMPlatformRenderConfiguration",
"listItemHeight": "70",
"listItemIconHeight": "60",
"platform": "IPAD",
"maxHeadingLength": "Default"
},
Something like this would good too :
"maxHeadingLength": "this.items[0].maxHeadingLength"
Thanks
Update, It seems I can and need to precise the question a bit better now.
I'd like to write any string expression into the pure JSON string data(file), as string of course and evaluate the data within the same data set without using "eval".
Thanks to all !
You can either do this in a backend process or using a front end process as you process the JSON.
Let's assume you're wanting to do it in the front end using JS, I would suggest firstly setting the items[0].maxHeadingLength as a var, like so:
var defaultMaxHeadingLength = items[0].maxHeadingLength;
And then as you loop through your JSON you can check whether the maxHeadingLength attribute has a value or not and default it, like so:
var item, i;
for ( i = 0; i < items.length; i++ )
{
item = items[ i ];
item.maxHeadingLength = item.maxHeadingLength ? item.maxHeadingLength : defaultMaxHeadingLength;
}
Here's an idea of one way to do it (if I understand what you're trying to do):
var defaultItem = {
"maxHeadingLength": {
P: 300,
L: 400
}
};
var jsondata = {
items: [
{
"class": "pmedia.types.PMPlatformRenderConfiguration",
"listItemHeight": "70",
"listItemIconHeight": "60",
"platform": "IPAD",
"maxHeadingLength": this.defaultItem.maxHeadingLength
}
]
};
alert(jsondata.items[0].maxHeadingLength.L);
//returns 400
Basically you have a default item separate to all your other items, allowing you to refer to the defaults in the main data.
I don't think you can use this.jsondata from within the same object, since it hasn't finished being created yet (but I could be wrong).