Google books api returns missing parameters - json

I am making a react app that searches for a book by title and returns the results.
It's mostly working fine, but for some titles searched (such as "hello") it can't get the results because the parameters are missing.
Specially, the "amount" value is missing, and it can get me e-books that are not for sale even if I add the filter=paid-ebooks param while fetching the api. Using projection=full doesn't help either.
For example, when I call the api with
https://www.googleapis.com/books/v1/volumes?printType=books&filter=paid-ebooks&key=${APIKEY}
and use the fetched data inside books array in reactjs:
this.props.books.map((book, index) => {
return (
<CardItem
key={index}
title={book.volumeInfo.title}
authors={book.volumeInfo.authors ?
book.volumeInfo.authors.join(', ') :
"Not provided"}
price={book.saleInfo.listPrice.amount}
publisher={book.volumeInfo.publisher}
addToCart={() =>
this.props.addItem(this.props.books[index])}
/>
)
})
One of the results it gets is like this:
"saleInfo": {
"country": "TR",
"saleability": "NOT_FOR_SALE",
"isEbook": false
}
While it should be like, what's expected is :
"saleInfo": {
"country": "TR",
"saleability": "FOR_SALE",
"isEbook": true,
"listPrice": {
"amount": 17.23,
"currencyCode": "TRY"
}
And trying to search with this api answer throws the error :
TypeError: Cannot read property 'amount' of undefined
price={book.saleInfo.listPrice.amount}
As you can see in react code's authors, this issue comes up with authors parameter too, which I've bypassed as seen in the code. But I cannot do the same with amount. Is this a known error in Google Books API or is there a way to prevent this? I don't understand why it still returns me e-books that are not for sale even with filter=paid-ebooks param.

I have not dug into the API documentation. An ideal solution would be a query param that only sends back books with a list price (like you tried with filter=paid-ebooks). Because that's not working, a simple fix would be to filter your results once you get them.
Assuming the response contains an array of book objects, it would look something like this:
const paidBooks = apiResponse.data.filter(book => book.listPrice)
This code will take the response from the API, and filter out all books that do not contain a truthy value for listPrice

That totally right, actually i never used react but the same logic try using try{ }catch(error){} for those missing data

Related

Fetching Reddit posts in React using Axios, weird JSON path

I'm trying to get the titles of reddit posts from a subreddit in React, using Axios for fetching.
I can fetch the JSON from here, and would like to get the data of each object (post/comment) separately (so I can show titles, post text and the like in the render() part of the component).
Here's the first lines of that JSON, pretty-printed:
{
"kind": "Listing",
"data": {
"modhash": "",
"dist": 27,
"children": [
{
"kind": "t3",
"data": {
"approved_at_utc": null,
"subreddit": "reactjs",
"selftext": "Previous two threads - [June 2019](https:\/\/www.reddit.com\/r\/reactjs\/comments\/bvxng8\/beginners_thread_easy_questions_june_2019\/) and [May 2019](https:\/\/www.reddit.com\/r\/reactjs\/comments\/bjgval\/beginners_thread_easy_questions_may_2019\/). \n\nGot questions about React or anything else in its ecosystem? Stuck making progress on your app? Ask away! We\u2019re a friendly bunch. \n\nNo question is too simple. \ud83e\udd14\n\n---------------------------------------------\n\n\ud83c\udd98 **Want Help with your Code?** \ud83c\udd98\n\n* **Improve your chances** by putting a minimal example to either [JSFiddle](https:\/\/jsfiddle.net\/Luktwrdm\/) or [Code Sandbox](https:\/\/codesandbox.io\/s\/new). Describe what you want it to do, and things you've tried. Don't just post big blocks of code!\n\n* **Pay it forward!** Answer questions even if there is already an answer - multiple perspectives can be very helpful to beginners. Also there's no quicker way to learn than [being wrong on the Internet](https:\/\/xkcd.com\/386\/). \n\n**Have a question regarding code \/ repository organization?**\n\nIt's most likely answered within this [tweet](https:\/\/twitter.com\/dan_abramov\/status\/1027245759232651270?lang=en).\n\n---------------------------------------------------\n\n**New to React?**\n\n**Check out the sub's sidebar!**\n\n\ud83c\udd93 Here are great, **free** resources! \ud83c\udd93\n\n* [Create React App](https:\/\/facebook.github.io\/create-react-app\/)\n* [Read the **official** Getting Started page](https:\/\/reactjs.org\/docs\/getting-started.html) on the docs.\n* [\/u\/acemarke](https:\/\/www.reddit.com\/u\/acemarke)'s [suggested resources for learning React](http:\/\/blog.isquaredsoftware.com\/2017\/12\/blogged-answers-learn-react\/)\n* [Kent Dodd's Egghead.io course](http:\/\/kcd.im\/beginner-react)\n* [Tyler McGinnis' 2018 Guide](https:\/\/medium.freecodecamp.org\/a-comprehensive-guide-to-react-js-in-2018-ba8bb6975597)\n* [Codecademy's React courses](https:\/\/www.codecademy.com\/catalog\/language\/javascript)\n* [Scrimba's React Course](https:\/\/scrimba.com\/g\/glearnreact)\n* [Robin Wieruch's Road to React](https:\/\/roadtoreact.com)\n\n-----\n\nAny ideas\/suggestions to improve this thread - feel free to comment here!\n\n----\n_Finally, an ongoing thank you to all who post questions and those who answer them. We're a growing community and helping each other only strengthens it!_",
"author_fullname": "t2_2aun3ozb",
"saved": false,
"mod_reason_title": null,
"gilded": 0,
"clicked": false,
"title": "Beginner's Thread \/ Easy Questions (July 2019)",
"link_flair_richtext": [
],
Here's my component (without the render part, just what happens after that fetch is complete - i.e. the componentDidMount() function):
componentDidMount() {
axios.get(`https://www.reddit.com/r/reactjs.json`)
.then (
res => {
const posts = res.data.data.children.map(obj => obj.data);
this.setState({posts});
}
);
}
This works perfectly.
My question is - why?
My logic would go - get res -> look for data -> look for children -> look for data, then map() that data object into the data object for posts.
Instead, what seems to work is - get res -> look for data -> look for data -> look for children, then do the mapping.
That's how axios parses the response json object. They store it under their own personal data key. It just so happens that within the json object provided by Reddit, they also have a field called data that holds the children array you want.
It might be more helpful to name your variables like so:
componentDidMount() {
axios.get(`https://www.reddit.com/r/reactjs.json`)
.then((res) => {
const redditJson = res.data
const posts = redditJson.data.children.map(obj => obj.data)
this.setState({
posts: posts
})
})
}

Accessing items in a list in AppleScript?

I'm trying to access items in a list via AppleScript. Try as I might, I can't seem to access them. I've pasted my code below
tell application "JSON Helper"
set result to fetch JSON from "https://newsapi.org/v2/top-headlines?sources=bbc-news&pageSize=1&apiKey=X"
set news to title of articles of result
end tell
set result_string to news & ""
Note, I've removed my api key. The api format is :
{"status":"ok","totalResults":10,"articles":[{"source":{"id":"bbc-news","name":"BBC News"},"author":"BBC News","title":"Trump urges Israeli 'care' on settlements","description":"The US president also casts doubt on whether the Palestinians or Israel are ready to talk peace.","url":"http://www.bbc.co.uk/news/world-middle-east-43025705","urlToImage":"https://ichef.bbci.co.uk/news/1024/branded_news/165CD/production/_99979519_044058382.jpg","publishedAt":"2018-02-11T16:47:27Z"}]}
I'm trying to access title but I keep getting "can't get title".
Any input would be much appreciated. Thanks!
Using the sample JSON data you gave, I used this command:
tell application "JSON Helper" to read JSON from ¬
"{
\"status\": \"ok\",
\"totalResults\": 10,
\"articles\": [
{
\"source\": {
\"id\": \"bbc-news\",
\"name\": \"BBC News\"
},
\"author\": \"BBC News\",
\"title\": \"Trump urges Israeli 'care' on settlements\",
\"description\": \"The US president also casts doubt on whether the Palestinians or Israel are ready to talk peace.\",
\"url\": \"http://www.bbc.co.uk/news/world-middle-east-43025705\",
\"urlToImage\": \"https://ichef.bbci.co.uk/news/1024/branded_news/165CD/production/_99979519_044058382.jpg\",
\"publishedAt\": \"2018-02-11T16:47:27Z\"
}
]
}"
to retrieve an AppleScript record. Pretty-printing it as I have above, however, you might already be able to see that articles is a list (containing one item). Therefore, whilst this:
set news to title of articles of result
produces an error, this:
set news to title of item 1 of articles of result
retrieves the correct datum.

REST POST json body to support complex query advice

I'm fairly new to REST. All of our legacy webservices were SOAP based with enterprise (ORACLE or DB2) databases. We are now moving to REST/couchbase.
Our team is looking into implementing a complex query method. We already have implemented simple query methods using GET, for example GET returns all entries and a GET/067e6162-3b6f-4ae2-a171-2470b63dff00 would return the entry for 067e6162-3b6f-4ae2-a171-2470b63dff00.
We want to support a query method that would support receiving several query parameters such a list of Ids and date ranges. The number of Ids can number into a few thousand and because of this, we realize we cannot pass these query parameters in a GET HTTP header since there is a limit on header size.
We are starting to look into passing our query parameters into the JSON body of a POST request. For example, we could have client pass in a few thousand Ids as an array and also pass in a date range, so we'd have each query param/filter be an object. The JSON body would then be an array of objects. For example:
{
"action" : "search",
"queryParameters" : {
[
{
“operation”: “in”,
"key" : "name.of.attribute.Id",
"value" : "[{ "id: "067e6162-3b6f-4ae2-a171-2470b63dff00"}, {"id": "next id"....}],
},
{
“operation”: “greater”,
"key" : "name.of.attribute “,
"value" : "8/20/2016"
},
{
“operation”: “less”,
"key" : "name.of.attribute “,
"value" : "8/31/2016"
}
]
}
The back end code would then receive POST and read the body. It would see action is a search and then look for any entries in the list that are in the list of Ids that are in the date range of > 8/20/2016 and < 8/31/2016.
I've been trying to look online for tips/best practices on how best to structure the JSON body for complex queries but have not found much. So any tips, guidance or advice would be greatly appreciated.
thanks.

Filters aren't applied when data comes from $http

This is kind of a next-step from filter data using dropdown?, and callmekatootie's answer-plunk (http://plnkr.co/edit/n7TebC). Taking that and a few other things, I've got two dropdowns that can act together/apart to filter the data set, and I've applied a limit so it'll only show 4 (and then four more on ng-click, etc). The current plunk is here: http://plnkr.co/edit/Sc283f.
If I set the data inside the scope (no $http), and turn off the quantity limit, the two filters work perfectly.
If I add the limit first, like this:
<li data-ng-repeat="item in data | limitTo:quantity | filter:customFilter">
then it's giving me the first 4 items in data and then applying the filter, which in some cases gets me nothing. But if I reverse that and get the data first:
<li data-ng-repeat="item in data | filter:customFilter | limitTo:quantity">
the limit only works the first time. Change either filter and the limit no longer seems to apply regularly/correctly/something.
And if I change the data to come in via $http, none of it works. I just get the entire set, no filter, no limit. I could probably live with and/or figure out a way around and/or eventually fix the first two issues (the filters and the limit) but I just can't see any reason why the filters/limit work (mostly) when the data is local, but fail when the data's coming in through $http.
I'm sure I'm missing something really obvious and simple, but hell if I know. Anyone?
The test data is an array of animals...
[
{ animal : 'dog', color : 'blue'},
{ animal : 'cat', color : 'red'}
]
But the JSON downloaded by $http is an object with an animal in each property...
{
"0": {"title": "...", "animal": "dog", "color": "purple"},
"1": {"title": "...", "animal": "cat", "color": "yellow"}
}
Angular's built in filter only accepts arrays, which is why it's being bypassed when you give it an object instead.
You can change the service to return an array, or you can transform the data to an array when returned from $http with a function like this...
function toArray(data) {
var items = [];
angular.forEach(data, function (value) {
items.push(value);
});
return items;
}
$http.get('demo.json').success(function(data) {
$scope.data = toArray(data);
});
Updated Plunker

Iterating through couchbase keys without a view

In couchbase, I was wondering if there was a way - WITHOUT using a view - to iterate through database keys. The admin interface appears to do this, but maybe its doing something special. What I'd like to is make a call like this to retrieve an array of keys:
$result = $cb->get("KEY_ALBERT", "KEY_FRED");
having the result be an array [KEY_ALEX, KEY_BOB, KEY_DOGBERT]
Again, I don't want to use a view unless there's no alternative. Doesn't look like its possible, but since the "view documents" in the admin appears to do this, I thought i'd double-check. I'm using the php interface if that matters.
Based on your comments, the only way is to create a simple view that emit only the id as par of the key:
function(doc, meta) {
emit( meta.id );
}
With this view you will be able to create query with the various options you need :
- pagination, range, ...
Note: you talk about the Administration Console, the console use an "internal view" that is similar to what I have written above (but not optimized)
I don't know about how couchbase admin works, but there are two options. First option is to store your docs as linked list, one doc have property (key) that points to another doc.
docs = [
{
id: "doc_C",
data: "somedata",
prev: "doc_B",
next: "doc_D"
},
{
id: "doc_D",
data: "somedata",
prev: "doc_C",
next: "doc_E"
}
]
The second approach is to use sequential id. You should have one doc that contain sequence and increment it on each add. It would be something like this:
docs = [
{
id: "doc_1",
data: "somedata"
},
{
id: "doc_2",
data: "somedata"
}
...
]
In this way you can do "range requests". To do this you form array of keys on server side:
[doc_1, doc_2 .... doc_N]and execute multiget query. Here is also a link to another example
The couchbase PHP sdk does support multiget requests. For a list of keys it will return an array of documents.
getMulti(array $ids, array $cas, int $flags) : array
http://www.couchbase.com/autodocs/couchbase-php-client-1.1.5/classes/Couchbase.html#method_getMulti