I'm going to develop a pushing server (HTML5 WebSocket/Polling) and in order to reduce the size of packets (that presents in JSON format) I want to do something like this with packets:
[["id", "username", "password"], [1, "afshin", "123"], [2, "barak", "meme"]]
Instead of clear JSON format like:
[{"id": 1, "username": "afshin", "password": "123"}, {"id": 2, "username": "barak", "password": "meme"}]
Exactly, I want to prevent sending contract properties in each object.
So, I want to know is there any library for doing this (or something like)? I have C# on server and JavaScript on clients.
JSON DB or RJSON should be exactly what you're looking for. You'll most likely have to implement serializers/deserializers yourself (RJSON is already implemented in JS though).
As for compressing pure JSON, I think you could bypass the "keys are needed" rule by wrapping all your data in a single object entry:
{"data" : [["id", "username", "password"], [1, "afshin", "123"], [2, "barak", "meme"]]}
So, besides all the arguments against manual compression, this would be a solution:
var input = [{"id": 1, "username": "afshin", "password": "123"}, {"id": 2, "username": "barak", "password": "meme"}];
var keys = {}
input.map ( function (e) { Object.keys(e).map( function (k) { keys[k] = 1; })});
var output = [ Object.keys(keys) ] .concat( input.map( function (e) {
return Object.keys(keys).map( function (k) { return e[k]; } );
} ) );
console.log(output);
and Node.js produces:
[ [ 'id', 'username', 'password' ],
[ 1, 'afshin', '123' ],
[ 2, 'barak', 'meme' ] ]
I really don't know if this works with every browser etc.
By removing the name of the name-value pair you'd be breaking a JSON syntax rule. Effectively, it wouldn't be JSON. You also might cause problems for JSON client deserialization. Could you consider reducing the length of your names:
[{"id": 1, "u": "afshin", "p": "123"}, {"id": 2, "u": "barak", "p": "meme"}]
This JSON document is the same size as the one you propose above.
Related
The issue is that I'm trying to get a JavaScript object like the following:
[
"id" : 11,
"name" : "Peter"
"other": {
"id": 22,
"item": 534
},
"main": false
]
Since I want to get this via reactjs: I trying to do this:
http.get(API.BASE_URL + API.USER_INFO)
.accept('Application/json')
.end((err, res) => {
//console.log(x);
console.log(err);
console.log(res);
});
When I try a normal json string I get the right result, but with this javascript object I get:
Error: Parser is unable to parse the response
undefined
Has anyone come across this before? Any idea?
What you're trying to parse isn't valid JSON (as well as JavaScript) because you've written it out as an array, but still use key/value pairs as if it were an object. Try this instead:
{
"id": 11,
"name": "Peter",
"other": {
"id": 22,
"item": 534
},
"main": false
}
I am new to AngularJS. Trying to get specific element from a JSON array via $resource.
The structure of JSON file staffs.json is like:
[{
"id": 0,
"facility_id": [0],
"name": "Tim",
"role_id": 0
},
{
"id": 1,
"facility_id": [0],
"name": "Duncan",
"role_id": 0
},
{
"id": 2,
"facility_id": [0],
"name": "Tony",
"role_id": 1
},
{
"id": 3,
"facility_id": [0],
"name": "Parker",
"role_id": 1
},
{
"id": 4,
"facility_id": [0],
"name": "Manu",
"role_id": 2
},
{
"id": 5,
"facility_id": [0],
"name": "Ginobili",
"role_id": 2
},
{
"id": 6,
"facility_id": [0],
"name": "Tiago",
"role_id": 3
},
{
"id": 7,
"facility_id": [0],
"name": "Splitter",
"role_id": 3
}]
I am trying to get a staff whose name is "Tiago".
The code is:
var url = 'data/staffs.json';
var username = 'Tiago';
users = $resource(url);
users.get({name: username}, function(data){
alert(data.name);
});
It seems the alert() function inside the get() never gets called. However if I changed the method from users.get() to users.query(), it can get the list of the staffs. I guess this is because the data inside the JSON file is an array, so the query() which is used to get array works, while the get() does not work because it is not for array operation. Am I correct?
I am just wondering if I have to use query() get the whole array and match the elements one by one until I find the one with the same name, or there are some simpler ways to get the element I want.
Thanks
AngularJS resource has a separate query function to avoid JSONP vulnerability for arrays. You have two options:
get all and find the element in the array on the client side
add extra API endpoint for single user and fetch it by the name
I vote for option two, since you don't have to send everything over the wire and you use server (DB) to get the specific user. Server software is optimised for that.
Your best bet would by fetching data with the query() method, then using indexOf()
var url = 'data/staffs.json';
var username = 'Tiago';
users = $resource(url);
users.get({name: username}, function(data){
dataOfMyUser = data.map(function(cur) { return cur.name }).indexOf(username);
alert(dataofMyUser);
});
What is the right way to format your responses in JSON and why? I've seen different services do it two ways, consider a simple GET /users resource:
{
"success": true,
"message": "User created successfully",
"data": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
That is how I usually do that. I have some abstract helper fields like success and message, there may be some more but the question is if should I nest the data in the data field to an array called the same way as the resource - users:
{
"success": true,
"message": "User created successfully",
"data": {
"users": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
}
Even if we don't use the abstraction:
{
"users": [
{"id": 1, "name": "John"},
{"id": 2, "name": "George"},
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Jane"}
]
}
Seems the users key is obsolete as any client will know the route they called, which consists of /users, where users are mentioned, and the client code like
$users = $request->perform('http://this.api/users')->body()->json_decode();
looks much better than
$users = $request->perform('http://this.api/users')->body()->json_decode()->users;
as it avoids repeated users.
One use case where the envelope can be useful is when you are expecting to be dealing with large lists and need to do pagination to prevent huge response payloads. The envelope is a good place to put the pagination meta data:
{
"users": [...],
"offset": 0,
"limit": 50,
"total": 10000
}
(This is what we do in a RESTful API I'm working on)
Clearly this is only relevant for requests that return lists of things (e.g. /users/) and not for requests that return single entities (e.g. /users/42) and even for requests that return lists, you don't have to use an envelope - one alternative would be to use response headers for this meta data instead.
PS. I would only advise having a success and message fields if you have a concrete use case for them. Otherwise don't bother, they are simply unnecessary.
Just to get on the same page, data is a field in a JSON object. In the first example the value of data is an array. In the second example the value of data is an object.
Either is valid, so to answer your question: no it is not necessary to nest named objects in an named object. It is necessary that all fields of an object be named, but you are free to nest arrays within an object.
It really just depends on what the processor expects. If data can be anything, then the first approach is fine. If code expects the value of the data field to be an object, then you have to use something like the second example.
According to your comment which you added to first comment: more descriptive data is better data as every information is useful for consumer of you API - REST endpoint. So if you know that the content is user, or whatever, it's better to use it in schema or endpoint url.
Better description = better consuption :-)
there!
I´ve one column in my jqGrid that is empty.
But i checked the object on chrome console and thats fine.
colModel definition
colModel:[
{name:'id',index:'id', width:55,editable:false,editoptions:{readonly:true,size:10},hidden:true},
{name:'firstName',index:'firstName', width:100,searchoptions: { sopt: ['eq', 'ne', 'cn']}},
{name:'lastName',index:'lastName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}},
{name:'books[0].nome',index:'books[0].nome', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}},
{"formatter":"myfunction", formatoptions:{baseLinkUrl:'/demo/{firstName}|view-icon'}}
]
JSON response
{
"total": "10",
"page": "1",
"records": "3",
"rows": [
{
"id": 1,
"firstName": "John",
"lastName": "Smith",
"books": [{"nome": "HeadFirst"}]
},
{
"id": 2,
"firstName": "Jane",
"lastName": "Adams",
"books": [{"nome": "DalaiLama"}]
},
{
"id": 35,
"firstName": "Jeff",
"lastName": "Mayer",
"books": [{"nome": "Bobymarley"}]
}
]
}
chrome console inspect object
rowdata.books[0].nome
"HeadFirst"
Any one know where theres are possibles trick?
Tks!
You should use as the value of name property of colModel only the names which can be used as property name in JavaScript and as CSS id names. So the usage of name:'books[0].nome' is not good idea.
To solve your problem you can use jsonmap. For example you can use dotted name conversion:
{name: 'nome', jsonmap: 'books.0.nome', ...
In more complex cases you can use functions as the value of jsonmap. For example
{name: 'nome', jsonmap: function (item) {
return item.books[0].nome;
}, ...
You can find some more code examples about the usage of jsonmap in other old answers: here, here, here, here, here.
name is intended to be a unique name for the row, not a reference to a JSON object. From the jqGrid colModel options documentation:
Set the unique name in the grid for the column. This property is required. As well as other words used as property/event names, the reserved words (which cannot be used for names) include subgrid, cb and rn.
You can also observe how .name is used within grid.base.js - for example:
var nm = {},
...
nm = $t.p.colModel[i].name;
...
res[nm] = $.unformat.call($t,this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
Anyway, to get back to your question I think you will have better luck by passing down the book name directly - as strings and not objects - and referencing it by name as something like bookName.
I'm storing location data in Couchdb, and am looking for a way to get an array of just the values, instead of key: value for every record. For example:
The current response
{"total rows": 250, "offset": 0, "rows":[
{"id": "ec5de6de2cf7bcac9a2a2a76de5738e4", "key": "user1", "value": {"city": "San Francisco", "address":"1001 Bayhill Dr"},
{"id": "ec5de6de2cf7bcac9a2a2a76de573ae4","key": "user1", "value": {"city": "Palo Alto", "address":"583 Waverley St"}
... (etc).
]}
I only really need:
[{"city": "San Francisco", "address":"1001 Bayhill Dr"},
{"city": "Palo Alto", "address":"583 Waverley St"},
...]
The reason for all this is to minimize the amount of bandwidth that a JSON response consumes.
I can't seem to find a way to transform the view into a simple array. Any suggestions?
Thanks.
You can use _show and _list functions, they take either a document or a view (respectively) and can send back a transformed response in whatever format you need. (in this case, JSON)
Update: I ran a simple test with the data you provided here on my own CouchDB. Here's the list function I ended up writing. Customize it to fit your needs. :)
function (head, req) {
// specify that we're providing a JSON response
provides('json', function() {
// create an array for our result set
var results = [];
while (row = getRow()) {
results.push({
city: row.value.city,
address: row.value.address
});
}
// make sure to stringify the results :)
send(JSON.stringify(results));
});
}