I have some JSON that when converted to an Object it looks like the following:
{
'SOME RANDOM STRING':
{
'Article Headline': 'headline',
'Article Image URL': 'image url',
'Article Published Date': 'date',
'Article URL': 'article url',
'Category': 'mental illness,',
'Location': 'place',
'Source Name': 'source'
}
}
I have it stored in an array called results. How would I be able to access the values within Location as result.location doesn't work.
If its a JSON, you don't have to convert it into an array. You can parse it directly something like below.
var obj = {
'-KzZaDXhWRwdzfKUf5tl':
{ 'Article Headline': 'headline',
'Article Image URL': 'image url',
'Article Published Date': 'date',
'Article URL': 'article url',
'Category': 'mental illness,',
'Location': 'place',
'Source Name': 'source' }
}
console.log(obj['-KzZaDXhWRwdzfKUf5tl'].Location);
The above prints place to the screen.
The path to the Object would be results[0]['RANDOM STRING'].location, however since you don't know the RANDOM STRING then it'd be best to use non referential methods to access the nested object.
Thankfully there are many tools in recent version of NodeJS/Javascript to do just this!
Array.prototype.map(function(item, index, array), context) seems like the function you want! It will create a new array based on the return of the function as applied to each thing in the array.
Then you can change each object by using other tools built onto the object itself like
// array of keys, useful for looking for a specific key
Object.keys(someReallyObtuseObject)
// array of VALUES! Awesome for looking for a specific data type
Object.values(someReallyObtuseObject)
Checking Node Green for Object.values shows it's available in NodeJS 7.10 or greater and for Object.keys shows it is available as far back as 4.8.6!
Don't forget though that these transform the object to an array. After that you can use forEach, filter, map, and many other array methods to access the data!
An Example
Say I have an array from a database called results
const results = [{...},{...},...];
I want to find a result with the identifier I know
// I will either find the result, or receive undefined
let result = results.filter(r => r[key] == identifier)[0];
However in my result the object has a key called "related posts" and it is an object with a key being a unique ID for each related post. I want to access said posts, but I don't know their unique IDs, so I want to convert it to an array to make processing it easier
// This gives me an array of related posts with their ID now nested inside them
let relatedPosts = Object.keys(result['related posts']).map(k => {
let r = result['related posts'][k];
r.id = k;
return r;
});
Now I can go over my related posts easily, and I never had to know the ID of the post. Let's say I want to console.log each post(you would really never want to do this)
relatedPosts.forEach(console.log);
Easy!
Example 2, getting the location from an array of users
Users are defined as an object with keys 'first', 'last', 'location'
const users = [{...},{...},...]
let locations = users.map(user => user.location)
Related
I have a number of posts in the table wp_3_posts with the post_type "people". This post_type is created using the Admin Columns plugin.
How do I retrieve these?
The documentation for Posts offers filtering by categories or tags but post_type is neither of these.
https://developer.wordpress.org/rest-api/reference/posts/
Thank you :]
If I got your question the right way, you want to get posts of a custom post type with REST API.
You have to set show_in_rest and public in the arguments when you create the custom post type in wordpress.
add_action( 'init', 'my_cpt' );
function my_cpt() {
$args = array(
'public' => true,
'show_in_rest' => true,
'label' => 'My Custom Post'
);
register_post_type( 'mycustompost', $args );
}
More about this: https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-rest-api-support-for-custom-content-types/
With that having set, you can get the posts of post type with using the right parameters in the url.
So if you just want to get posts, you can use:
https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10
I would suggest setting the per_page to have control if you are getting a lot of posts.
You can also have access to more data without additional HTTP requests using _embed
https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10&_embed=wp:term,wp:featuredmedia
For example, with this you get taxonomy terms and urls of different featured image sizes.
So you do not need to get all posts (and post types) of your website and then filter by post type, but just get posts of this post type instead. You can than do more filtering using global parameters:
https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/
With VueJS (in my opinion better performance) this would look something like:
fetch("https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10")
.then(response => response.json())
.then((data => {
this.mycustompost = data;
}))
Or if using standard javascript something like:
let state = {
posts: [],
baseUrl: 'https://yoursite.com/wp-json/wp/v2/mycustompost',
perPage: '?per_page=10',
wpFetchHeaders: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Expose-Headers': 'x-wp-total'
}
}
}
Given this query here,
let output = [];
const sql = `select * from coredb.account LIMIT ${offset},${limit}`;
let data = await sequelize.query(sql, null, {raw: true, type: sequelize.QueryTypes.SELECT});
data.forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
the data variable is indeed hydrated with the right row data when using console.log to inspect it.
But, when I try to access the individual properties, they only ever come back as undefined. This TextRow object that Sequelize seems to return the result in doesn't seem to want to let me access then explicit rows.
Just curious what i'm missing here, am I missing an option?
I agree, Sequalize raw queries are not intuitive. You don't need the null or raw: true flag. Something like this should work:
let data = await sequelize.query(sql, {type: sequelize.QueryTypes.SELECT});
When I tried this, "data" was an array of two objects, each being the query result. So, the properties can be accessed by using index [0].... e.g.
data[0].forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
Not yet sure WHY this occurs!
EDIT - it's because .query() should have only two arguments. Changing the call to: sequelize.query(sql, {raw: true, type: sequelize.QueryTypes.SELECT}) resulted in data being a single array (as expected).
Finally I was able to find the solution for it.
You just need to make a new array and push data into it by finding bases on key name like this:
suppose we have data in students object:
let finalArray = new Array();
for (var k in students ) {
finalArray.push(students[k])
}
console.log(finalArray) // Normal JSON array object :)
m.sequelize.query(sql, {
model,
mapToModel: true
})
.then(model => res.status(200).send(model))
.catch(error => res.status(400).send(error.toString())
})
I am trying to populate the project select dropdown with data from the server.
I am using yii2.
My controller data action:
public function actionData()
{
$list = new OptionsConnector(null, "PHPYii");
$list->render_table("project", "id", "id(value),name(label)");
$connector = new JSONSchedulerConnector(null, "PHPYii");
$connector->set_options("project", $list);
$connector->configure(
new Booking(), "id", "start, end, activity, user, subsubproject, status, comment"
);
$connector->render();
}
I get an error message:
Exception 'Error' with message 'Call to a member function find() on
string'
And I think this line is the cause: $connector->set_options("project", $list);
What should I change?
UPDATE:
So I am here now:
public function actionData() {
$list = new JSONOptionsConnector(null, "PHPYii");
$list->enable_log("text1.log");
$list->configure(
new Subsubproject(),
"-","id, name"
);
$list->render();
$connector = new JSONSchedulerConnector(null, "PHPYii");
$connector->enable_log("text2.log");
$connector->set_options("subsubprojects", $list);
$connector->configure(
new Booking(),
"id", "start, end, activity, user, subsubproject, status,comment"
);
$connector->render();
}
and I get this:
0: Object { key: undefined, id: 1, name: "Thing1", … }
1: Object { key: undefined, id: 2, name: "Thing2", … }
2: Object { key: undefined, id: 3, name: "Thing3", … }
I don't have keys... How can I get some? :)
1) You don't need to call the render method of JSONOptionsConnector directly. Calling it ends processing of the request if I'm not mistaken, so the SchedulerConnector takes no effect
Try commenting out $list->render(); line.
2) The response format seems a bit off. This may be a bug of PHPYii wrapper of dhtmlx connector, I'm not sure
According to source codes the client-side needs value and label properties from options, and while handler returns id and name.
You can try something following:
public function actionData() {
$list = new JSONOptionsConnector(null, "PHPYii");
$list->enable_log("text1.log");
$list->configure(
new Subsubproject(),
"id","id(value), name(label)"
// or
// "id(value)","id(value), name(label)"
);
$connector->enable_log("text2.log");
$connector->set_options("subsubprojects", $list);
$connector->configure(
new Booking(),
"id", "start, end, activity, user, subsubproject, status,comment"
);
$connector->render();
}
This should produce a json response containing a list of booking and subprojects.
However, I can't test this code so something may still be wrong.
You can try it and see whether the result JSON looks right.
If it doesn't get you any closer, I honestly would produce json manually rather than using a connector with PHPYii wrapper. That way you'll have direct control over what is returned from your controller and won't have another black box there.
You'll need to return a json of the following structure from your action:
https://docs.dhtmlx.com/scheduler/data_formats.html#jsonwithcollections
so you'll have something like this in your action:
return $this->asJson([
"data"=> $preparedEventsArray
"collections" => [
"subprojects"=> $preparedSubprojects
]
]);
where $preparedEventsArray is an array of event objects as shown in docs, and $subprojects - your value/label objects
Note that names of properties in the data collection - "id","start_date","end_date","text" - are mandatory, you'll have to map your data model to this structure,
e.g.
start -> start_date
end -> end_date
activity -> text
all other properties can have their names unchanged.
The official docs don't have a sample code for Yii2, unfortunately.
There are common docs for server formats
https://docs.dhtmlx.com/scheduler/server_integration.html
And tutorials for PHP Slim framework and Laravel, which is not exactly what you need, but the closest thing the current documentation has.
I need to create a database of shopify orders so I can run advanced queries and sales reports that you can't do in the shopify admin area. I'm building in Sails .12 and mysql. Shopify lets you register a webhook so that every time an order is placed, it creates a POST to the specified URL with the order data in the body as JSON. The products ordered are an array of JSON objects as one of the values in the POST:
{
"id": 123456,
"email": "jon#doe.ca",
"created_at": "2017-01-10T14:26:25-05:00",
...//many more entires
"line_items": [
{
"id": 24361829895,
"variant_id": 12345,
"title": "T-Shirt",
"quantity": 1,
"price": "140.00",
},
{
"id": 44361829895,
"variant_id": 42345,
"title": "Hat",
"quantity": 1,
"price": "40.00",
},
]
}
I need to save the order into an Orders table, and the products ordered into a line_items table that is a one to many relation; one order can have many line_items (products ordered). There are over 100 key-value pairs sent by the webhook, and I'm saving all of it. I've created my two models where I define the data type, so now i have very long Order.js and Line_item.js files, and I'm using the
line_items: {
collection: 'line_item',
via: 'order_id'
},
in my Order.js, and
order_id: {
model: 'order'
},
in my Line_item.js models to relate them. Is this the correct way to denfine my two tables? Also, where would I put the code that maps the JSON to the model parameters? If I put that code in the controllers, would I have to type another 100+ lines of code to map each json value to its correct parameter. The how would I save to the two different models/tables? Eg:
var newOrder = {};
newOrder.id =req.param('id');
newOrder.email = req.param('email');
newOrder.name = req.param('name');
...//over 100 lines more, then Order.create(newOrder, ...)
var newLine_items = req.params('line_items'); //an array
_.forEach(newLine_items, function(line_item){
var newLine_item = {};
newLine_item.id = line_item.id;
newLine_item.order_id = newOrder.id;
newLine_item.title = line_item.title;
//etc for over 20 more lines, then Line_item.create(newLine_item, ...)
});
I need to save the order into an Orders table, and the products ordered into a line_items table that is a one to many relation; one order can have many line_items (products ordered).
That sounds completely reasonable, well, besides the use of the Oxford comma :)
There are over 100 key-value pairs sent by the webhook
I'm not sure that I understand exactly what this is or what it is used for within this process.
That being said, it might help to have a single attribute in your model for this which has a JSON value, then retrieve and work with it as JSON instead of trying to manually account for each attribute if that is what you're doing over there?
It really depends on your use case and how you'll use the data though but I figure if the format changes you might have a problem, not so if it's just being stored and parsed as a JSON object?
Also, where would I put the code that maps the JSON to the model parameters
In v0.12.x take a look at Services.
In v1, Services will still work but moving this logic into Helpers might be a good option but then, it seems that a custom model method would be a better one.
Here is a shorter version of your code:
var newOrder = req.allParams();
newLine_items = {};
_.forEach(newOrder.line_items, function(line_item) {
newLine_items.push(line_item);
});
Here is what your logic might look like:
var newOrder = req.allParams();
// Store the order
Order
.create(newOrders)
.exec(function (err, result) {
if (err) // handle the error
var newLine_items = {};
_.forEach(newOrder.line_items, function(line_item) {
// Add the order id for association
line_item.order_id = result.id;
// Add the new line item with the orders id
newLine_items.push(line_item);
});
// Store the orders line items
LineItems
.create(newLine_items)
.exec(function (err, result) {
if (err) // handle the error
// Handle success
});
});
And the lifecycle callback in the Order model:
beforeCreate: function (values, cb) {
delete(values.line_items);
cb();
}
But you really should look into bluebird promises as the model methods in version one of sails have opt in support for them and it helps to negate the pyramid of doom that is starting in my example and is also something that you want to avoid :P
I'm having a little problem and couldn't figure it out. I created a table with checkbox and it's working and can save to json without a problem. Now i wanna make my checkboxes have their default values set from json data when the page loads (to make it easier to edit). Anyway here is my code:
//row index
var index = 0;
//gets full info of student
var responseStudent = rpc.call('db.findOne', ['StudentAnket', {
'_id': '${this.objId}'
}]);
result = responseStudent['result'];
//gets info needed for my table
//{anket: true, request: true, statement: false, etc...}
var resultMat = result['listmaterial'];
//materials is a list which contains id, name of rows
materials.forEach((m) {
//creating table body
index = index + 1;
tbody.append(new Element.tr()
..append(new TableCellElement()..text = index.toString())
..append(new TableCellElement()..append(new LabelElement()
..text = m['name']
..setAttribute('for', m['id'])))
..append(new TableCellElement()..append(new InputElement()
..id = m['id']
..type = "checkbox"
..checked = "VALUE TAKEN FROM JSON")));
});
So how can i get keys and values from resultMat and set checked property for each checkbox?
Edit:
List materials = [{
'id': 'anket',
'name': 'Student anket'
}, {
'id': 'request',
'name': 'Request'
}, {
'id': 'statement',
'name': 'Statement'
}, {
'id': 'marklist',
'name': 'Mark List'
}];
Your information how your materials structure looks like is not clear. A List has only one value not two ('id, 'name of rows'). First you have to ensure that your JSON is not a String but a Dart data structure (Lists, Maps, values).
You can take a look at the answers to this questions to learn how this works
Dart Parse JSON into Table
Then you should be able to access the value like
..checked = resultMat[m['id']] ;