HttpRequest.getString hitting error function even though its succeeding - json

Wondering if anyone here could help?
Using Polymer Dart I've set up a service to load a Json feed using the following code:
Future loadService(){
return HttpRequest.getString(_serviceURL)
.then(buildView)
.catchError(handleError);
}
When this code executed, it does successfully hit my buildView function, but I'm also getting an error printed out from my handle error function:
void handleError(Error error){
print(error);
}
I have 3 items in my json feed:
[
{
"module": "module-1",
"data": {
"title": "Dynamic Title 1",
"text": "This is the dynamic text for content block 1."
}
},
{
"module": "module-2",
"data": {
"title": "Dynamic Title 2",
"text": "This is the dynamic text for content block 2."
}
},
{
"module": "module-3",
"data": {
"title": "Dynamic Title 3",
"text": "This is the dynamic text for content block 3."
}
}
]
The error I'm getting is: "RangeError: 3".
I can't find a lot of information about what could be causing this. It doesn't seem to be hindering my app, but I would like to clear it up if at all possible. If anyone has any suggestions, I'm all ears.
Thanks!
Edit: as per the suggestion by Günter Zöchbauer
Now I understand the .catchError() function catches errors from the .then() function. I thought it was only going to catch errors around the HttpRequest itself failing.
In buildView I was looping through the json object using a for loop like this:
void buildView(String jsonString){
contentBlocks = JSON.decode(jsonString);
DivElement wrapper = $['content-modules-wrapper'];
for(int i=0; i < contentBlocks.length; i++){
Element element = new Element.tag(contentBlocks[i]['module']);
wrapper.children.add(element);
}
}
Which is wrong, because .length takes the JSON string length (300 something characters) which i think is a bit weird since I've converted it to an object.. anyway, i fixed it by changing the function to this:
void buildView(String jsonString){
contentBlocks = JSON.decode(jsonString);
DivElement wrapper = $['content-modules-wrapper'];
contentBlocks.forEach((block){
Element element = new Element.tag(block['module']);
wrapper.children.add(element);
});
}
Is there a way to get the number of items in a json object like I was trying to do or should you always just loop through it using forEach()?

This error is probably from your buildView. The indexes of the result are from 0 to 2 not from 1 to 3.

Related

Cypress Access Array element API response nested json

I cannot quite figure out how to access the 0th element in the array as part of the JSON body in order to check the API response. I have tried various ways and none seem to be correct.
I currently have the following as an example:
I'm guessing it is not difficult but for the life of me I can't figure it out. Thanks!
cy.get('#dogs')
.its('body')
.its('breeds[0]')
.its('names')
.should('include', {
count: ('10'),
});
Refer its. The indexes should be accessed individually with its.
Response JSON:
{
"sample": [
{ "names": ["Dummy 1", " Dummy 2"] },
{ "names": ["Dummy 3", " Dummy 4"] },
{ "names": ["Dummy 5", " Dummy 6"] }
]
}
The last object in the array should be accessed as:
// to check a child's length
cy.get('#sample')
.its('body') // 'responseBody' in case of latest cypress version
.its('sample')
.its('2')
.its('names')
.its('length')
.should('eq', 2);
// To check content
cy.get('#sample')
.its('body') // 'responseBody' in case of latest cypress version
.its('sample')
.its('2')
.its('names')
.its(1)
.should('include', '6');
Screenshot:

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.

Chatfuel redirect_to_blocks does not work

I have a problem with my chatfuel JSON API from my node JS app.
I try to catch an error and return a message + a redirect_to_block to be able to ask the user again.
My error detection works well and if I try to display a message only it works. My JSON is :
[{"text":"Please type again"}]
But I can't add a redirect_to_blocks to this (and I even loose the text message display).
I tried those solutions (and probably some more) but I think I didn't get the JSON structure :
// Solution 1
[{ "message": { "text": "Please type again" }, "redirect_to_blocks": ["When?"] }]
// Solution 2
[{ "messages": { "text": "Please type again" }, "block_names": ["When?"], "type": "show_block", "title": "go" }]
// Solution 3
[{ "text": "Please type again" }, "redirect_to_blocks": ["When?"] }]
And here is the block I want to add (i'm not even sure the name I have to give to the JSON)
Thanks !
Julian, workaround that works for me is returning from API following JSON:
{
"set_attributes": {
"redirectBlock": <your block name>
}
}
and build structure in Chatfuel as below:
Chatfuel flow
Now you have a dispatcher that allows you to map values from API to block titles.
I had your same issues,
I created a json request in my Flow that returns this json:
{ "redirect_to_blocks": ["Block name"] }
but Chatfuel never redirects to it.
I solved it creating a new block in "Automate" pane with same name and It works.
I know that it's passed much time since your question,
but I hope it can helps future issues.

Best way to know which property has the error deserializing JSON?

I am currently getting invlaid JSON back from TFS similar to the following:
{
"value": [
{
"version": 46874,
"changeDate": "2016-10-27T11:18:37.14Z",
"size"/8,
"hashValue": "ADnOi7g3m13IlYXnt9Q5Qw==",
"path": "$/some/random/file",
"url": "https://example.com/blah"
}, //...
],
"count": 14
}
While the TFS admins figure out what is wrong with TFS, I've decided that the, while undesirable, not having the file's size is not crucial to the project and I want to just ignore this error for now.
Google lead me to this question. If I wanted to ignore all errors, this would be fine. I only want to ignore the error for the size property. So I wrote this error handler:
public void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
if (errorArgs.ErrorContext.Path.EndsWith(".size"))
errorArgs.ErrorContext.Handled = true;
}
Unfortunately, errorArgs.ErrorContext.Path is value[2].changeDate when parsing the line "size"\8,. This seems wrong.
I could store the response in a field before deserialization and then use errorArgs.ErrorContext.Error.LinePosition like so:
public void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
var pos = (errorArgs.ErrorContext.Error as JsonReaderException)?.LinePosition ?? 0;
if (pos > 6 && _parseData.Substring(pos - 6,6) == "\"size\"")
errorArgs.ErrorContext.Handled = true;
}
This seems awkward though. Does anyone have a better suggestion?

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
}
}