Spyne: How to decode POST into JSON using HttpRpc - json

I am trying to build a REST application using sypne. I want to receive a JSON document (but not with with the method called as the name of the object. I give en example to clarify:
I make a POST to the URL http://localhost/root with the following content:
{ "id": 1, "desc": "number" }
And I have my spyne application:
class HelloWorldService(ServiceBase):
#rpc(_returns=AnyDict)
def root(ctx):
json_in=""
for data in ctx.in_string:
json_in = json_in + data
return json.loads(json_in)
application = Application([HelloWorldService],
tns='com.hello.webservices',
in_protocol=HttpRpc(validator='soft'),
out_protocol=JsonDocument()
)
And I know there has to be a better way of doing this! Any pointers to documentation or solution appreciated in advance!
Regards

Spyne doesn't have that functionality ouf the box, you need to implement your own protocol for that.
It's pretty easy though. Off the top of my head:
class HybridHttpJsonDocument(JsonDocument):
def create_in_document(self, ctx):
super(HybridHttpJsonDocument, self).create_in_document(ctx)
# get url fragment from ctx.transport.req_env
ctx.in_document = {url_fragment: ctx.in_document}
That's all I can think of that you need to do. Please report back with your results!
Best regards,

Related

Returning a specific JSON object using Express

So let's say I've got a massive JSON file, and the general structure is roughly like so:
{
"apples": { complex object },
"oranges": { complex object },
"grapes": { complex object }
}
Is there some way to specifically target an object to return while using express? As in, say, if someone made a simple get request to my server, it'd return specifically the given object(s). I know the syntax and concept is completely wrong in this instance but for lack of a better way to say it, something like...
let testData = 'testdata.json';
app.get('/thing', res => {
res.json(testData.oranges);
}
I know you can return the entire file, but that adds a good amount of loading time in this instance, and is impractical in this particular case.
Or, alternatively - would it be better to have node parse the JSON file and split it into an apples.json, oranges.json, etc files to use? Trying to understand A, the best practice for doing something like this, and B, the most effective way to translate this into a practical application for a medium sized project.
Any thoughts or advice along this line - even if it's a library recommendation - would be greatly appreciated.
It should work if you make a POST request caring the payload of the specific 'thing', and then returning an object based on that thing. Example:
let testData = {
"apples": { complex object },
"oranges": { complex object },
"grapes": { complex object }
};
app.post('/route', (req, res) => {
thing = req.body.thing;
res.json(testData[thing]);
}
This is a GET request for some data and essentially since the JSON file can be used as a key/value store to query for the desired response data.
Assuming the query parameter for specifying the desired key for the object to return is part then the following example would work:
const testData = require('./testdata.json');
app.get('/thing', (req, res) => res.json(testdata[req.query.part]);
Querying for /thing?part=apples would return testdata.apples in the response.

Angular2 HTTP Providers, get a string from JSON for Amcharts

This is a slightly messy questions. Although it appears I'm asking question about amCharts, I really just trying to figure how to extract an array from HTTP request and then turn it into a variable and place it in to 3-party javacript.
It all starts here, with this question, which was kindly answered by AmCharts support.
As one can see from the plnker. The chart is working. Data for the chart is hard coded:
`var chartData = [{date: new Date(2015,2,31,0,0,0, 0),value:372.10,volume:2506100},{date: new Date(2015,3,1,0, 0, 0, 0),value:370.26,volume:2458100},{date: new Date(2015,3,2,0, 0, 0, 0),value:372.25,volume:1875300},{date: new Date(2015,3,6,0, 0, 0, 0),value:377.04,volume:3050700}];`
So we know the amCharts part works. Know where the problem is changing hard coded data to a json request so it can be dynamic. I don't think this should be tremendously difficult, but for the life of me I can't seem figure it out.
The first issue is I can't find any documentation on .map, .subscribe, or .observable.
So here is a plunker that looks very similar to the first one, however it has an http providers and injectable. It's broken, because I can't figure out how to pull the data from the service an place it into the AmCharts function. I know how pull data from a http provider and display it in template using NgFor, but I don't need it in the template (view). As you can see, I'm successful in transferring the data from the service, with the getTitle() function.
this.chart_data =_dataService.getEntries();
console.log('Does this work? '+this.chart_data);
this.title = _dataService.getTitle();
console.log('This works '+this.title);
// Transfer the http request to chartData to it can go into Amcharts
// I think this should be string?
var chartData = this.chart_data;
So the ultimate question is why can't I use a service to get data, turn that data into a variable and place it into a chart. I suspect a few clues might be in options.json as the json might not be formatted correctly? Am I declaring the correct variables? Finally, it might have something to do with observable / map?
You have a few things here. First this is a class, keep it that way. By that I mean to move the functions you have inside your constructor out of it and make them methods of your class.
Second, you have this piece of code
this.chart_data =_dataService.getEntries().subscribe((data) => {
this.chart_data = data;
});
What happens inside subscribe runs asynchronously therefore this.chart_data won't exist out of it. What you're doing here is assigning the object itself, in this case what subscribe returns, not the http response. So you can simply put your library initialization inside of the subscribe and that'll work.
_dataService.getEntries().subscribe((data) => {
if (AmCharts.isReady) {
this.createStockChart(data);
} else {
AmCharts.ready(() => this.createStockChart(data));
}
});
Now, finally you have an interesting thing. In your JSON you have your date properties contain a string with new Date inside, that's nothing but a string and your library requires (for what I tested) a Date object, so you need to parse it. The problem here is that you can't parse nor stringify by default a Date object. We need to convert that string to a Date object.
Look at this snippet code, I used eval (PLEASE DON'T DO IT YOURSELF, IS JUST FOR SHOWING PURPOSES!)
let chartData = [];
for(let i = 0; i < data[0].chart_data.length; i++) {
chartData.push({
// FOR SHOWING PURPOSES ONLY, DON'T TRY IT AT HOME
// This will parse the string to an actual Date object
date : eval(data[0].chart_data[i].date);
value : data[0].chart_data[i].value;
volume : data[0].chart_data[i].volume;
});
}
Here what I'm doing is reconstructing the array so the values are as required.
For the latter case you'll have to construct your json using (new Date('YOUR DATE')).toJSON() and you can parse it to a Date object using new Date(yourJSON) (referece Date.prototype.toJSON() - MDN). This is something you should resolve in your server side. Assuming you already solved that, your code should look as follows
// The date property in your json file should be stringified using new Date(...).toJSON()
date : new Date(data[0].chart_data[i].date);
Here's a plnkr with the evil eval. Remember, you have to send the date as a JSON from the server to your client and in your client you have to parse it to a Date.
I hope this helps you a little bit.
If the getEntries method of DataService returns an observable, you need to subscribe on it to get data:
_dataService.getEntries().subscribe(
(data) => {
this.chart_data = data;
});
Don't forget that data are received asynchronously from an HTTP call. The http.get method returns an observable (something "similar" to promise) will receive the data in the future. But when the getEntries method returns the data aren't there yet...
The getTitle is a synchronous method so you can call it the way you did.

Nested JSON-response from Magento-REST in Sencha Touch 2's Store

I'm having a hard time using my product-store's proxy on a response coming from magento 1.7
The response looks like this:
{
"1":
{"entity_id":"1","type_id":"simple","sku":"dress_test","status":"1","visibility":"4","tax_class_id":"2","weight":"1.0000","price":"1500.0000","special_price":"1000.0000","name":"Wedding dress","url_key":"dress","country_of_manufacture":"AO","msrp_display_actual_price_type":"2","gift_message_available":"1","news_from_date":"2012-03-21 00:00:00","news_to_date":"2012-03-24 00:00:00","special_from_date":"2012-03-21 00:00:00","special_to_date":"2012-03-24 00:00:00","description":"White wedding dress"},
"2":
{"entity_id":"2","type_id":"simple","sku":"black_sunglasses","status":"1","visibility":"4","tax_class_id":"2","weight":"0.2000","price":"500.0000","special_price":"300.0000","name":"Sunglasses","url_key":"sunglasses","country_of_manufacture":"AR","msrp_display_actual_price_type":"2","gift_message_available":null,"news_from_date":null,"news_to_date":null,"special_from_date":"2012-03-21 00:00:00","special_to_date":"2012-03-24 00:00:00","description":"Black sunglasses"}
}
But the input expected from sencha (I think) should look like this:
{
{"entity_id":"1","type_id":"simple","sku":"dress_test","status":"1","visibility":"4","tax_class_id":"2","weight":"1.0000","price":"1500.0000","special_price":"1000.0000","name":"Wedding dress","url_key":"dress","country_of_manufacture":"AO","msrp_display_actual_price_type":"2","gift_message_available":"1","news_from_date":"2012-03-21 00:00:00","news_to_date":"2012-03-24 00:00:00","special_from_date":"2012-03-21 00:00:00","special_to_date":"2012-03-24 00:00:00","description":"White wedding dress"},
{"entity_id":"2","type_id":"simple","sku":"black_sunglasses","status":"1","visibility":"4","tax_class_id":"2","weight":"0.2000","price":"500.0000","special_price":"300.0000","name":"Sunglasses","url_key":"sunglasses","country_of_manufacture":"AR","msrp_display_actual_price_type":"2","gift_message_available":null,"news_from_date":null,"news_to_date":null,"special_from_date":"2012-03-21 00:00:00","special_to_date":"2012-03-24 00:00:00","description":"Black sunglasses"}
}
How can I change the behaviour of the proxy to be able to store the loaded data into my store?
Many thanks in advance!
To customize your own response you have to subclass Ext.data.reader.Reader
Reader or in your case Json class converts data from the response to result set is accepted by Sencha's Model/Proxy/Store.
Cheers, Oleg
add
Ext.define('lib.data.reader.Json', {
extend: 'Ext.data.reader.Json',
alias : 'reader.magentojson', ...
})
than use later reference on the reader: 'magentojson'
and you keep original reference to 'json' reader!

Converting velocity response to JSON

I am using struts 2 and velocity templates to generate JSON response.
Now the catch is the response is not generated using some velocity JSON plugin
it's just a String that comes out once velocity is done with its parsing and rendering of
response, and on client side I do eval to get the response from string to JSON.
What I really need is some solution on velocity's or struts' side where, once the result is
generated by velocity, the framework should call my API where I can convert the response output of vm file into JSON using my own logic. How do achieve this?
For example:
On browser using JavaScript I have designed a tree widget that I use for displaying comments in tree structure.
Say user clicks on comments button.
My UI widget will fire an AJAX to get data for comments.
This request is intercepted by STRUTS 2 framework.
It will call, say, getComments() action API and will populate an arrayList with comment object say cmt.
Now the response is handled by a velocity template(*.vm).
Now in vm I am writing code like this:
{ "CommentsData" : [
#set($sep="")
#foreach($c in $cmt)
$sep
{
"commentText" : $c.getText()
}
#set($sep=",")
#end
}
Now the final response may turn out like this:
{ "CommentsData" : [
{
"commentText" : "This is comment 1"
},
{
"commentText" : "This is comment 2"
},
{
"commentText" : "This is comment 3"
},
{
"commentText" : "This is comment 4"
}`
]
}
Now this may look like JSON, but its not strict JSON; I mean if I miss
some , somewhere then on client side in JavaScript my eval might fail or JSON.parse()
will fail, but on velocity template I have now clue if JSON is malformed.
So once the above velocity template is generated I need some control, where I can write some Java code to do some validations on the response.
I see that my approach to use velocity template to generate JSON output (actully a String that looks like JSON) may be wrong. But still I need to handle the response of every velocity template I have written.
Not sure how you are using velocity. We don't use velocity when outputting JSON; we just create a JSON convertible object and output it directly from controllers using response.write(jsonObject.toJson()). This way, proper JSON is always generated.

Provide JSON as data for rich:extendedDataTable

I am implementing a full text search in my project and for that the result of search comes from SOLR server as JSON.
Is it possible to provide JSON for data or value attribute of the richfaces component extendedDatatTable or simple dataTable.
Resultant JSON would look something like :
`resultObj = {
"numberOfResults":25,
"results":[
{
"instanceId":100,
"inj_Name":"Inj4",
"i_IdentificationNumber":127,
"noz_Name":"Nozzle4",
"n_IdentificationNumber":460,
"thr_Name":"Throttleplate4",
"t_IdentificationNumber":0,
"act_Name":"Atuator4",
"a_IdentificationNumber":781
},
{
"instanceId":100,
"inj_Name":"Inj4",
"i_IdentificationNumber":127,
"noz_Name":"Nozzle4",
"n_IdentificationNumber":460,
"thr_Name":"Throttleplate4",
"t_IdentificationNumber":0,
"act_Name":"Atuator4",
"a_IdentificationNumber":781
} ]
};
`
Regards,
Satya
As far as I know, no you can't. Your best bet would be to reflect this data into a List of Java objects using Gson and then use that list as a data source.