Organize data on hybrid-mobile-app - json

I am developing an Ionic app that must be able to operate offline. Being so I receive from the backend a JSON object called data that contains all the info I need and this object get updated at times using a diff algorithm.
The data comes like that:
{
"foos": [
{"id": 1, "name": "foo1"},
{"id": 2, "name": "foo2"}
],
"bars": [
{"id": 1, "name": "bar1", "fooId": 1},
{"id": 2, "name": "bar2", "fooId": 2}
]
}
I would like to have a specialized layer from where I can call for example findFooById(bars[i].fooId)
I am wondering what is the best way to achieve that and if there is something out of the box.

I think your best solution is to revisit your data structure in general as it looks overly complicated and I can't see a benefit to it.
But, general algorithm would be easy:
function findFooById(fooId) {
for (var x = 0; x < foos.length; x++){
if (foos[x].id == fooId) { return foos[x]; }
}
return false;
}

Related

Get the Json object from a array of Json objects using Groovy

I want to get the productLines for the prodType ULTRA for the Json array below. I get the array of maps and uses findIndexValues to get the index but
it doesn't work. What am I missing? I looked at similar examples which are less complex in structure and did not see much difference from what I'm attempting
Here is my data:
def static modelData="""
{
"models": [
{
"transactionId": "01-PROD0021",
"prodCode": "ISN-2017WDE",
"product": "VASCULAR DNNT",
"prodType": "SDISCNT",
"productLines": [
{
"productLineId": "ELECT-2221",
"productDescriptor": "XTRA-SONIC DNNP",
"unitPrice": "",
},
{
"productLineId": "ELECT-2223",
"productDescriptor": "HEADPH",
"unitPrice": "1.33",
}
]
},
{
"transactionId": "01-PROD0024",
"prodCode": "ISN-5543XDR",
"product": "ULTRASOUND DEEP SONAR",
"prodType": "ULTRA",
"productLines": [
{
"productLineId": "MEDCN-XTR221",
"productDescriptor": "ELECTRONIC RESPR",
"unitPrice": "2.44",
},
{
"productLineId": "MEDCN-XTR376",
"productDescriptor": "SPNG ELECTRONIC DEFIB",
"unitPrice": "6.22",
}
}
]
]
}
"""
Here is my attempt:
def parsed = new JsonSlurper().parseText(modelData)
// Find index of the prodCode with 'ULTRA'
int [] vals=parsed.data.findIndexValues{
it -> it.key=='prodType' && it.value=='ULTRA'}
//Does not print anything
vals?.each {println "Found an index! ${it}" }
There's a couple of things wrong with the code:
1. You loop through a "data" node, where there is none. Use parsed.data
2. The each node is a map-like structure. Hence you check if the map contains a key prodType with value ULTRA. Use it.prodType == 'ULTRA'.
Pro-tip:
1. You can print what the data looks like on closures so that you will get to the solution quicker.
I was able to figure it out
def parsed = new JsonSlurper().parseText(modelData)
def vals = parsed.models.find{ it.prodType == 'ULTRA' }?.productLines

Is it necessary to have a set of objects nested in a named object

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 :-)

Smaller JSON Format

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.

Identifying Duplicates in CouchDB

I'm new to CouchDB and document-oriented databases in general.
I've been playing around with CouchDB, and was able to get familiar with creating documents (with perl) and using the Map/Reduce functions in Futon to query the data and create views.
One of the things I'm still trying to figure out is how to identify duplicate values across documents using Futon's Map/Reduce.
For example, if I have the following documents:
{
"_id": "123",
"name": "carl",
"timestamp": "2012-01-27T17:06:03Z"
}
{
"_id": "124",
"name": "carl",
"timestamp": "2012-01-27T17:07:03Z"
}
And I wanted to get a list of document id's that had duplicate "name" values, is this something I could do with the Futon Map/Reduce?
The result was hoping to achieve is as follows:
{
"name": "carl",
"dupes": [ "123", "124" ]
}
..or..
{
"carl": [ "123", "124" ]
}
.. which would be the value, and associated document ids which contain those duplicate values.
I've tried a few different things with Map/Reduce, but so far as I understand, the Map function works with data on a per-document basis, and the Reduce functions only allow you to work with the keys/values from a given document.
I know i could just pull the data I need with perl, work magic there, and get the result I want, but I'm trying to work only with CouchDB for now in order to better understand it's benefits / limitations.
Another way I'm thinking about doing this is to use a single document like an RDBMS table:
{
"_id": "names",
"rec1": {
"_id": "123",
"name": "carl",
"timestamp": "2012-01-27T17:06:03Z"
},
"rec2": {
"_id": "124",
"name": "carl",
"timestamp": "2012-01-27T17:07:03Z"
}
}
.. which should allow me to use the Map/Reduce functions in the way I originally thought. However I'm not sure if this is ideal.
I understand that my mind is still stuck in RDBMS land, so much of what I'm trying to do above may not be necessary. Any insight on this would be much appreciated.
Thanks!
Edit: Fixed JSON syntax in some of the examples.
If you merely want a list of unique values, that's pretty easy. If you wish to identify the duplicates, then it gets less easy.
In both cases, a map function like this should suffice:
function (doc) {
emit(doc.name);
}
For your reduce function, just enter _count.
Your view output will look like: (based on your 2 documents)
{
"rows": [
{ "key": "carl", "value": 2 }
]
}
From there, you will have a list of names as well as their frequency. You can take that list and filter it yourself, or you can take the "all couch" route and use a _list function to perform that final filtering.
function (head, req) {
var row, duplicates = [];
while (row = getRow()) {
if (row.value > 1) {
duplicates.push(row);
}
}
send(JSON.stringify(duplicates));
}
Read up about _list functions, they're pretty handy and versatile.

How should a JSON response be formatted?

I have a REST service that returns a list of objects. Each object contains objectcode and objectname.
This is my first time building a REST service, so I'm not sure how to format the response.
Should it be:
{
"objects": {
"count": 2,
"object": [
{
"objectcode": "1",
"objectname": "foo"
},
{
"objectcode": "2",
"objectname": "bar"
},
...more objects
]
}
}
OR
[
{
"objectcode": "1",
"objectname": "foo"
},
{
"objectcode": "2",
"objectname": "bar"
},
...more objects
]
I realize this might be a little subjective, but which would be easier to consume? I would also need to support XML formatted response later.
They are the same to consume, as a library handles both just fine. The first one has an advantage over the second though: You will be able to expand the response to include other information additional to the objects (for example, categories) without breaking existing code.
Something like
{
"objects": {
"count": 2,
"object": [
{
"objectcode": "1",
"objectname": "foo"
},
{
"objectcode": "2",
"objectname": "bar"
},
...more objects
]
}
"categories": {
"count": 2,
"category" : [
{ "name": "some category"}
]
}
}
Additionally, the json shouldn't be formatted in any way, so remove whitespace, linebreaks etc. Also, the count isn't really necessary, as it will be saved while parsing the objects themselves.
I often see the first one. Sometimes it's easier to manipulate data to have meta-data. For exemple google API use first one : http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true
It's not only the question of personal preference; it's also the question fo your requirements. For example, if I was in the same situation and I did need object count on client side then I'd go with first approach otherwise I will choose the second one.
Also please note that "classic" REST server mostly will work a bit different way. If some REST function is to return a list of objects then it should return only a list of URLs to those objects. The URLs should be pointing to details endpoints - so by querying each endpoint you may get details on specific single object.
As a client I would prefer the second format. If the first format only includes the number of "objects", this is redundant information.