Ember error when json response root key is singular - json

I am getting an Ember error when the response json root is singular.
json response:
{"subscription": {"id": "1"}}
error:
Assertion failed: Your server returned a hash with the key subscription but you have no mapping for it
model:
App.Subscription
If I pass a plural root key subscriptions in the json response, it works fine. I don't think I should have to do this though since the singular version is default behavior for active
_model_serializers if there is only one resource to send.
Is this a bug in Ember or should I be doing something for this to be supported?

What might help is to define plurals on your adapter. So in the case of a model called App.Subscription this could look like this:
App.Adapter = DS.RESTAdapter.extend();
App.Adapter.configure('plurals', { "subscription": "subscription" });
Edit
As for the .json one possible solution might be to hook into the buildURL function of your RESTAdapter and adding the .json suffix yourself. This could look something like this:
App.Adapter = DS.RESTAdapter.extend({
buildURL: function(record, suffix) {
var url = this._super(record, suffix);
return url + ".json";
}
})
This would make a request to http://localhost:4000//subscription.json
Hope it helps.

Related

Postman: POST request of nested JSON via form-data not working (while via raw-data ok)

I want to POST the following JSON-object via Postman:
{
"title": "test_title",
"date": "2021-12-31",
"attachments": [
{
"name": "test_attachment"
}
]
}
This works perfectly fine, when using Postman's raw input form for the request-body: I get a "201 Created"-response back.
However, when using the form-data to POST the data, I get the error "Invalid data. Expected a dictionary, but got str." (see also screenshot below) What am I doing wrong here? I tried all kind of other versions to enter the attachment-key:value pair but nothing worked so far
I managed to make it work! (note: I added some additional fields compared to the screenshot in question. See below for details:
You did nothing wrong.
If you want to make a request with json object, then you go with raw type (json) in postman.
If you want to upload file, then you use form-data
One more thing, status 201 means the request is succeed, your object has been created.
var express = require('express')
const multer = require('multer')
const upload = multer()
var app = express()
app.use(express.json());
app.post('/test',upload.none(), function (req, res, next) {
res.send(req.body)
})
app.listen(80, function () {
console.log('web server listening on port 80')
})
Above is a sample endpoint which works with both form-data and json , just do a post to http://localhost:80/test with both form data and raw json
you can see both will get parsed correclty
APIs are just abstraction , its like a function that takes in many attribute, how you parse it depends on the implementation ( how the api function is written) .
so answer is "Talk to the developer" on how the API is implemented and what it is supporting
I'm having issue in placing json into form format the way Daniel did in Postman. Need help in figuring out what is it required to place the cascaded json objects into form data format. Please see here that I'm trying to accomplish.
JSON Format (to be filled into Postman form-data section:
{
"primary_object": {
"child_object_1": [{"id": 12345678, "value": "abc"},{"id": 87654321, "value": "xyz"}],
"child_object_2": [
"first_val",
"second_val"
]
}
}

NodeJS and HTTP: How to send JSON content in a POST/PUT call as a string rather than creating a new key

I built an API service that will process REST requests and use them to perform CRUD operations on a MongoDB instance. This application is standalone (by design) and should be a passthrough for anything that calls it. My other application that I built in Angular is calling this API to interact with my MongoDB instance. I have been trying to construct my JSON payload from a form, which works fine. I get something like:
{ "_id":"111111111", "name":"herp", "address":"derp", "city":"foo", "state":"bar", "zip":"11111", "phone":"111-222-3333"}
I am then trying to take that JSON and send it along to the service, but something is getting lost in translation once the service gets a hold of it and my variable name that contains the JSON object is being turned into an actual key in the request, with the JSON as its value. I am calling the service like this:
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' })
};
updateStuff(update){
console.log("Sending: " + JSON.stringify(update) + " for update");
return this.http.put('http://localhost:3000/api/test/_update', {dbName:"testDb",collection:"testing",update}, httpOptions);
}
Which logs:
Sending: {"name":"blah","address":"111 Anystreet","city":"MyCity","state":"NY","zip":"11111","phone":"555-111-2222","_id":"5ba914df13236f7a6ea3e233"} for update
So I know that right before the call is made, the data is fine. However, on the other side, it sees the following when it gets the data:
Received request: {"dbName":"testDb","collection":"testing","update":{"name":"blah","address":"111 Anystreet","city":"MyCity","state":"NY","zip":"11111","phone":"555-111-2222","_id":"5ba914df13236f7a6ea3e233"}}
instead of what I intended, which is below:
{"dbName":"testDb","collection":"testing","name":"blah","address":"111 Anystreet","city":"MyCity","state":"NY","zip":"11111","phone":"555-111-2222","_id":"5ba914df13236f7a6ea3e233"}
How do I tell the HTTP request to send the data itself rather than constructing a new key with the name "update" and sticking the payload in there as its value? I tried JSON.stringify, but that ends up sending the same thing, but with a bunch of backslashes in front of all the parenthesis. It still sends it all in a key with the name "update" as well. Any help would be greatly appreciated.
Your problem is here:
{dbName:"testDb",collection:"testing",update}
The statement above is shorthand for this:
{dbName:"testDb",collection:"testing",update:update}
What you're looking to do is this:
{dbName:"testDb",collection:"testing",...update}
Which is shorthand for this:
const data = {dbName:"testDb",collection:"testing"};
for (let key in update) {
if (update.hasOwnProperty(key)) {
data[key] = update[key];
}
}

Unable to access data inside a string (i.e. [ object Object ]) that was originally sent as a JSON object

I'm using axios to send a JSON object as a parameter to my api. Before it post request is fired, my data starts of as a JSON object. On the server side, when I console.log(req.params) the data is returned as such
[object Object]
When I used typeof, it returned a string. So then I went to use JSON.parse(). However, when I used that, it returned an error as such
SyntaxError: Unexpected token o in JSON at position 1
I looked for solutions, but nothing I tried seemed to work. Now I'm thinking I'm sending the data to the server incorrectly.
Here's my post request using axios:
createMedia: async function(mediaData) {
console.log("SAVING MEDIA OBJECT");
console.log(typeof mediaData)
let json = await axios.post(`http://localhost:3001/api/media/new/${mediaData}`)
return json;
}
Any thoughts on how I can solve this?
You need to update your code using axios to provide the mediaData in the body of the request instead of the URL:
createMedia: async function(mediaData) {
console.log("SAVING MEDIA OBJECT");
console.log(typeof mediaData)
let json = await axios.post(`http://localhost:3001/api/media/new/`, mediaData)
return json;
}
In the backend (assuming you're using express here), you need to configure your application to use bodyParser:
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
And then in your controller update your console.log(req.params) to console.log(req.body); then restart your node server

Angular resource 404 Not Found

I've read other posts that have similar 404 errors, my problem is that I can correctly query the JSON data, but can't save without getting this error.
I'm using Angular's $resource to interact with a JSON endpoint. I have the resource object returning from a factory as follows:
app.factory('Product', function($resource) {
return $resource('api/products.json', { id: '#id' });
});
My JSON is valid and I can successfully use resource's query() method to return the objects inside of my directive, like this:
var item = Product.query().$promise.then(function(promise) {
console.log(promise) // successfully returns JSON objects
});
However, when I try to save an item that I've updated, using the save() method, I get a 404 Not Found error.
This is the error that I get:
http://localhost:3000/api/products.json/12-34 404 (Not Found)
I know that my file path is correct, because I can return the items to update the view. Why am I getting this error and how can I save an item?
Here is my data structure:
[
{
"id": "12-34",
"name": "Greece",
"path": "/images/athens.png",
"description": ""
},
...
]
By default the $save method use the POST verb, you will need to figure out which HTTP verbs are accepted by your server en order to make an update, most modern api servers accept PATCH or PUT requests for updating data rather than POST.
Then configure your $resource instance to use the proper verb like this :
app.factory('Product', function($resource) {
return $resource('api/products.json', { id: '#id' }, {'update': { method:'PUT' }});
});
check $resource docs for more info.
NOTE: $resource is meant to connect a frontend with a backend server supporting RESTful protocol, unless you are using one to receive data & save it into a file rather than a db.
Otherwise if you are only working with frontend solution where you need to implement $resource and have no server for the moment, then use a fake one, there is many great solutions out there like deployd.
You probably don't implement POST method for urls like /api/products.json/12-34. POST method is requested from angular for saving a new resource. So you need to update your server side application to support it and do the actual saving.
app.factory('Product', function($resource) {
return $resource('api/products.json/:id', { id: '#id' });
});
Try adding "/:id" at the end of the URL string.

$http.get messing JSON parameters

I'm comunicating my Rails API with my AngularJS application.
Everything is working great and normal up until the point I have to send parameters in a GET request. This is the Rails controller
def cats
if cat_params[:color]
#cats = Cat.where(... #you know
else
//Do something else
end
private
def cat_params
params.require(:cat).permit(:color)
end
Then from Angular
var kitty = {
cat: {
color: "red"
}
}
$http.get('some URL', { params: kitty }).success.....
By this time, the params hash looks like a stringify JSON
Started GET "some URL?cat=%7B%22color%22:%22red%22%7D" for 127.0.0.1 at 2015-01-28 23:10:24 -0300
Processing by Some_controller as JSON
Parameters: {"cat"=>"{\"color\":\"red\"}", "cat_id"=>"19"}
Cat Load (0.5ms) SELECT "cat".* FROM "cats" WHERE "cat"."id" = 19 LIMIT 1
{"cat"=>"{\"color\":\"red\"}", "format"=>"json", "controller"=>"some_controller", "action"=>"some_action", "cat_id"=>"19"}
Completed 500 Internal Server Error in 95ms
NoMethodError - undefined method `permit' for "{\"cat\":\"red\"}":String:
I'm also sending the Content-Type header, set to 'application/json'.
From Angular's $http.get documentation, I read that if the value of params is something other than a string, it will stringify the JSON object, so the issue is not in the front-end.
I don't think the solution begins with starting JSON parsing the params hash, since I've had no need to do it in the past. It seems to me that strong_parameters is playing dirty, or Rails is ignoring the JSON string. Any ideas what to do next?
I just ran into the same issue. Changing the param serializer solved the issue for me:
$http.get('someURL', {
paramSerializer: '$httpParamSerializerJQLike',
params: {cat: {color: 'red}}
})
Also adding the 'Content-Type': 'application/json' header will not help since it applies to the the body the request.
I used to meet a $http.get problem that when call $http.get('some url', {params:SOME_PARAMS}), SOME_PARAMS could be transformd to key-value params when it is a simple key-value data like {color:'red'}, and it would transform params to json string when it is a complex type like {cat:{color:'red'}}.
So to solve your question, I suggest that add params behind url like:
$http.get('some URL?cat[color]=red').success.....