whats the best/recommended RESTful way to handle large single Json response? - json

When we have many documents to be returned from the response, we can paginate the result and give the link in the response to retrieve the next set of documents to be fetched from the API. However my case is different, each document in my response can be very large. How do I deal with such response ?
For Example consider the sample Json below:
{
"excludes": null,
"endDate": 1422918663,
"appliedText": "Applied text",
"id": "135699543",
...
"assignedTo": {
"productPart": [
{
"part": "1"
},
{
"part": "2"
},
{
"part": "3"
},
{
"part": "4"
},
...
]
}
...
}
If you see here, the productPart can grow to tens of thousands. How can I restrict such large response yet retain the structure.

Fetch product parts with a separate request (if you have the possibility) which then in turn can be paginated.
Alt. return the first x product parts and then provide a link where more product parts can be obtained.

I believe you should try something like JSON-Streaming.
Streaming Processing (also known as Incremental Processing) is the most efficient way to process JSON content. It has the lowest memory and processing overhead, and can often match performance of many binary data formats available on Java platform
Here is the main idea:
try {
InputStream in = [..];
JsonParser parser = new JsonFactory().createParser(in);
JsonToken token = null;
while ((token = parser.nextToken()) == JsonToken.FIELD_NAME) {
/*
* Parse parts and store them in client DB
* use later client side pagination
*
* {
* "part": "i"
* }
*/
}
} catch (Exception e) {
//
}

Related

Set variable from activity response Azure Data Factory

I have REST call in a Copy data activity which gives me a json response
My goal is to fetch the "hasNextPage" value and put it into the hasNext variable
I want to set it as a value in a "Set variable" activity that is connected to the "Copy data" activity, where I expected to acess the output in a way like this: #activity('Timesheets').output.data.timesheets.pageinfo.hasNext
I also want to be able to fetch the value of "cursor" from the last element in the "edges" array[]
I couldn't find any documentation on how to do this
Json response that I get from the Timesheets activity
[
{
"data": {
"timesheets": {
"pageInfo": {
"hasNextPage": true
},
"edges": [
{
"cursor": "81836000243260.81836000243275.",
"node": {
"parameter1": "2019-11-04",
"parameter2": "81836000243260"
}
},
{
"cursor": "81836000243252.81836000243260.81836000243275",
"node": {
"parameter1": "2019-11-04",
"parameter2": "81836000243260"
}
}
]
}
}
}
]
According to this, the output of an copy data activity don't have a data property you can access.
https://learn.microsoft.com/en-us/azure/data-factory/copy-activity-overview
Copy Activity are made for copying large data, and it doesn't copy all rows in one go.
So it would not make sense to have an output dataset for a Copy Activity.
If your response from your REST service contains limited element, you can use an Web Activity to consume the REST service.
This have an output dataset you can access.
Followed by a foreach activity to iterate the data set. Remember to take into consideration parallel vs sequential iteration of you data set in the foreach activity.
Note in your service response, you get an array of "data" objects, so you need to address the first "data" element.

Best Schema for a Data List in JSON for RestFul API to use in Angular

I've been wondering for some days what kind of scheme would be more appropriate to use a data list in json in a web application.
I'm developing a REST Web Application, and im using Angular for front end, i should order, filter and print these data list also in xml ...
For you what scheme is better and why?
1) {
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
}
2) {
"datas": [{
"data": { "first":"","second":""},
"data": { "first":"","second":""},
"data": { "first":"","second":""}
}]
}
3) [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
]
Thanks so much.
The first and third notations are quite similar because the third notation is included in your first.
So the question is "Should I return my datas as an array or should I return an object with a property that contain the array ?
It will depend on either you want to have more information alongside your datas or not.
For exemple, if your API might return an error, you will want to manage it from the front end.
In case of error, the JSON will looks like this :
{
"datas": null,
"error": "An error occured because of some reasons..."
}
At the opposite, if everything goes well and your API actually return the results, it will looks like this :
{
"datas": [
{ "first":"","second":""},
{ "first":"","second":""},
{ "first":"","second":""}
],
"error": null
}
Then your front end can use the error property to manage errors sent from the API.
var result = getDatas(); // Load datas from the API
if(result.error){
// Handle the error, display a message to the user, ...
} else {
doSomething(result.datas); // Use your datas
}
If you don't need to have extra properties like error then you can stick with the third schema.
The second notation is invalid. The datas array will contain only one object which will have one property named data. In this case data is a property that is defined multiple times so the object in the array will contain only the last occurence:
var result = {
"datas": [{
"data": { "first":"a","second":"b"},
"data": { "first":"c","second":"d"},
"data": { "first":"e","second":"f"}
}]
}
console.log("Content of result.datas[0].data : ")
console.log(result.datas[0].data)
Obviously the first option would be easy to use. Once you will access datas it'll give you an array. Any operation (filter, sort, print) on that array will be easy in comparison to anything else. Everywhere you just need to pass datas not datas.data.

POST request with large body received empty on server side

When issuing a POST request with a large body to my Play framework action method, I get null when extracting the data. If the body is fairly small, I can retrieve the data just fine.
Here's a sample short data set:
{
"creator": "zoltan",
"sport": "hike",
"geometry": [
{
"time": "2009-07-10 12:56:10 +0000",
"x": 10.275514,
"y": 47.514749,
"z": 756.587
},
{
"time": "2009-07-10 12:56:19 +0000",
"x": 10.275563,
"y": 47.514797,
"z": 757.417
}
]
}
When I issue a POST request with this JSON in the body, everything works fine. However, if I add many more (~4000) points in the geometry array, I get null in the action.
Here's my action method:
#Transactional
//#BodyParser.Of(Json.class) // tried with this as well
public static Result createTour() {
LOG.debug("Raw request body: " + request().body().asText());
JsonNode node = request().body().asJson();
LOG.debug("JSON request body: " + node);
TourDto tourDto;
try {
tourDto = jsonToTour(node);
int id = TourDataAccessUtils.create(tourDto);
return created(toJson(id));
} catch (JsonProcessingException e) {
LOG.error("While parsing JSON request.", e);
return Results.badRequest(
toJson(Throwables.getRootCause(e).getMessage()));
}
}
I tried using both Advanced REST Client in chrome and ċurl to send the request, both failed.
What could be the problem? Could it be that I need to include a Content-Lenght header for large requests? If so, how can I manually calculate it for arbitrary JSON data?
Please check the PlayFramework documentation, They mentionned that the default maximum length for request is 100KB:
Max content length
Text based body parsers (such as text, json, xml or
formUrlEncoded) use a max content length because they have to load all
the content into memory.
There is a default content length (the default is 100KB).
Tip: The default content size can be defined in application.conf:
parsers.text.maxLength=128K
You can also specify a maximum content length via the #BodyParser.Of
annotation:
// Accept only 10KB of data.
#BodyParser.Of(value = BodyParser.Text.class, maxLength = 10 * 1024)
pulic static Result index() {
if(request().body().isMaxSizeExceeded()) {
return badRequest("Too much data!");
} else {
ok("Got body: " + request().body().asText());
}
}

Facebook Graph API not returning standard JSON

I am working on an iOS app using the MonoTouch framework. I am using Visual Studio 2010 Professional SP1 with the Xamarin.iOS (v1.3.250) extension. I have been able to open a valid FacebookConnect.FBSession by using the FacebookConnect.FBLoginView with no issues but when I try to make a Graph API request using FacebookConnect.FBRequest I recieve a non-standard JSON style string. When I run following request through the Graph API Explorer:
me?fields=albums.fields(id,name,cover_photo)
I receive the following response:
{
"id": "111111111111111111",
"albums": {
"data": [
{
"id": "111111111111111111",
"name": "Some Album (#1)",
"cover_photo": "111111111111111111",
"created_time": "000-00-00T00:00:00+0000"
},
{
"id": "111111111111111111",
"name": "Some Album (#2)",
"cover_photo": "111111111111111111",
"created_time": "000-00-00T00:00:00+0000"
},
],
"paging": {
"cursors": {
"after": "xxxxxxxx=",
"before": "xxxxxxxx="
}
}
}
}
Now all of this is just fine and is what I expect to receive but when I make the same Graph API request from my app like this:
public static void GetPhotoAlbums(string _userID)
{
// _userID = "me"
mFBRequest = new FBRequest(FBSession.ActiveSession, _userID + "?fields=albums.fields(id,name,cover_photo)");
FBRequestConnection fbRequestConnection = new FBRequestConnection();
fbRequestConnection.AddRequest(mFBRequest, OnPhotoAlbumsReceived);
fbRequestConnection.Start();
}
static void OnPhotoAlbumsReceived(FBRequestConnection _connection, NSObject _result, NSError _error)
{
if (_error == null)
{
Console.WriteLine("FacebookManager.OnPhotoAlbumsReceived() - JSON: " + _result.Description);
object o = JsonConvert.DeserializeObject(_result.Description);
// ...
}
}
I receive this JSON 'like' response:
{
albums = {
data = (
{
"cover_photo" = 111111111111111111;
"created_time" = "000-00-00T00:00:00+0000";
id = 111111111111111111;
name = "Some Album (#1)";
},
{
"cover_photo" = 111111111111111111;
"created_time" = "000-00-00T00:00:00+0000";
id = 111111111111111111;
name = "Some Album (#2)";
},
);
paging = {
cursors = {
after = "xxxxxxxx=";
before = "xxxxxxxx=";
};
};
};
"id": "111111111111111111";
}
I'm not really sure how/why I'm getting a response formatted in a non-standard way but needless to say, I get Newtonsoft.Json.JsonReaderException when attempting to deserialize the data because it does not follow the standard formatting rules (ie, = instead of : to separate key/value pairs, ; instead of , to separate elements of a container, some keys having quotes while others do not, etc...)
I'm pretty new to Facebook and JSON stuff in general and am really at a loss for what is happening to the response string I receive. Any help, feedback, ideas are greatly appreciated. Thanks.
* Solution *
After a bunch of digging around it seems to be that the Graph API response is indeed JSON but it gets converted to an FBGraphObject which holds a NSMutableArray as it the data makes its way through the MonoTouch->.NET bindings so when I pulled _result.Description (equivalent to _result.ToString() it returned me the string representation of that object which happens to look a lot like JSON but is not. After finding all this out (and a lot of runtime experimentation), I was finally able to extract the data into a usable state by doing this:
static void OnPhotoAlbumsReceived(FBRequestConnection _connection, NSObject _result, NSError _error)
{
if (_error == null)
{
NSArray fieldData = (NSArray) _result.ValueForKeyPath(new NSString("albums.data.name"))
string[] names = NSArray.StringArrayFromHandle(fieldData.Handle);
// ...
}
}
Although this works for me, I have a feeling that there is a better or more robust way to get the data I requested, so if any developers out there can offer any additional tips for improving this solution, I would love to hear them.
As stated in Facebook SDK documentation Graph API:
When a request returns a non-JSON response (such as a "true" literal),
that response will be wrapped into a dictionary using this const as
the key. This only applies for very few Graph API prior to v2.1.
So you can check first if result is an NSDictionary, otherwise you can deserialize the JSON data as usual.
Below some obj-c code you can translate into C#/MonoTouch (I don't know the framework, I hope it is helpful).
NSDictionary *dict;
if ([graphResult isKindOfClass:[NSDictionary class]]) {
dict = (NSDictionary *)graphResult;
} else {
NSError *JSONError;
dict = [NSJSONSerialization JSONObjectWithData:graphResult options:NSJSONReadingAllowFragments error:&JSONError];
if (JSONError) {
NSLog(#"Facebook: JSON parse error: %#", JSONError);
// Handle error
}
}

get MongoDB results as objects instead of array

I'm new to MongoDB, and I'm trying to get results in a different way.
if I execute the query db.collection.find().toArray() I get something like:
[
{
"_id":"34234...",
"first":"Mark",
"last":"Marker"
},
{
"_id": "34235...",
"first":"Adam",
"last":"Smith"
}
]
is there an api that lets you to receive the results as the following?:
{
"results" : {
"34234..." :{
"_id":"34234...",
"first":"Mark",
"last":"Marker"
},
"4235..." :{
"_id": "34235...",
"first":"Adam",
"last":"Smith"
}
}
Or I need to get the results array and iterate every single object and build my response? (I would like to avoid the single cursor iteration)
I don't believe there's a native API function for that. cursor.toArray() goes through each item in the cursor begin with, so I wouldn't worry too much about that. We can just skip the toArray() and do our own iteration:
var obj = {}
db.collection.find().each(function(item){
obj[item._id] = item;
});
I don't think that would really be any slower.