Cannot convert JSON into Objects - flutter

i All,
The Project: A handy utility for tickets at work to help sort and manage my tickets, built on top of our provider's API.
My Background: I'm like 19 hours total into dart and am almost done with my first bootcamp.
The GIST: I have started writing a provider for our helpdesk software's API. I am sending requests to the API successfully but I am utterly clueless on transforming the data into an actual map to generate ticket instances with.
What I'm trying to accomplish:
Fetch the data from the API
Convert that String into a MAP of json objects that I can iterate
through
Iterate through the JSON objects to create instances of ticket
objects with
build a list of those ticket objects and return it to requestor to
generate a widget list.
I could swear I've done everything reasonable to try and type cast this as a map but I think there is something I just don't understand. FWIW I think whatever it is I'm trying to do is accessing a Future not the actual data. and I think i might be confused or unclear about async/awaits but my understanding of the code I've written is that the actions are chained one to another so I shouldn't be "waiting" for anything or getting a future, I should just be getting a string.
Otherwise, Here's my code cleaned up, any advice or suggestions on working with the data in the print would be much appreciated.
class ticketingsoftwareAPIProvider {
// Object Properties
Client _client = Client();
final String _ApiKey = "YOUSHALLPASS!";
final String apiRoot = "https://api.ticketingsoftware.com";
final String agentId = '2675309';
getAgentTickets() async {
// Headers for our HTTP Request
Map<String, String> headers = {
'X-ticketingsoftware-Authorization': 'Bearer $_ApiKey',
'Accept': 'application/vnd.ticketingsoftware.v2.1+json',
'Content-Type': 'application/json'
};
await _client
.get(Uri.parse('$apiRoot/incidents.json?assigned_to=$agentId'))
.then((data) {
if (data.statusCode == 200) {
print(json.decode(data.body));
// CANT SEEM TO MAKE THIS A INTO A MAP TO GENERATE OBJECTS WITH.
}
});
}
}
} // END CLASS
I apologize for any missing information, I am new to dart and REALLY programming in general and am still learning the culture. please let me know if there is any additional information that might help.
My Solution ended up being:
List ticketJson = json.decode(data.body);
for (var ticket = 0; ticket < ticketJson.length; ticket++) {
thisAgentsTickets.add(incident.fromJson(ticketJson[ticket]));
return thisAgentsTickets;
I think I've been learning from a very out of date course.

You need fromJson method to convert it to an object. For example
if (data.statusCode == 200) {
return AgentTicket = AgentTicket.fromJson(data.body)
}
Use json_serializable package for easy way to create the method, or you can create it manually too.

Related

How to store list<Object> to hive db

I have a question about hive db. is it possible to store List data type? That's what Hive's documentation says: Generic type parameters like Box are unsupported due to Dart limitations. But i need to store chat with room id and messages.
Lets imagine like that
that is, I need to store 2 different data types into the hive object, List (for message) and int (for id). is it possible? if you have any other ideas please share with me
Thanks
I have solved 🙂 this logic worked for me
final data = ChatStorage(
roomId: widget.room!.id,
chat: state.messages,
);
if (chatBox.isEmpty)
chatBox.put(widget.room!.id, data);
else {
List<int>? roomIds = [];
bool available = false;
for (var chat in chatBox.values) {
roomIds.add(chat.roomId!);
}
if (!roomIds.contains(widget.room!.id)) available = true;
if (available) chatBox.put(widget.room!.id, data);
}
}
I think this method will help if someone is facing such a problem 🙂

appwrite list users search params

I am trying to use appwrite server sdk list users to get userid from an email.
The documentation says there is a search: option that can be used but no where does it say what the format of that String? is.
What is the format of the search: String? to only get a list of users whose email matches?
void main() { // Init SDK
Client client = Client();
Users users = Users(client);
client
.setEndpoint(endPoint) // Your API Endpoint
.setProject(projectID) // Your project ID
.setKey(apiKey) // Your secret API key
;
Future result = users.list(search: '<<<WHAT GOES HERE>>>');
}
:wave: Hello!
Thanks for bringing this question up, this is definitely not well documented, I'll note this down and try to make it clearer in the docs, but here's how you'd approach this in Dart:
final res = users.list(search: Query.equal('email',
'email#example.com'));
res.then((response) {
print(response.users[0].toMap());
}).catchError((error) {
print(error);
});
The Query object generates a query string, and works similar to how listDocument would work. The difference here is that it only takes a single query string instead of a list.

How to make a REST delete method with cfhttp

I have never done it before and now when the need arise, things are not working.
I have to send an ID to delete a DB record with RESTful service. Here is the code I am trying:
<cfhttp url="http://127.0.0.1:8500/rest/test/something" method="DELETE" port="8500" result="qryRes1">
<cfhttpparam type="body" value="36"/>
</cfhttp>
and in the REST function
remote any function someName() httpmethod="DELETE"{
var testID = ToString(getHTTPRequestData().content);
//make db call to delete
return testid;
}
The result comes as blank [empty string]. I am not able to retrieve the sent value in function. What I am missing?
Edit: one slightly different but related to CF rest, is it necessary to convert query to an array before sending it back to client? Directly serializing won't solve the purpose same way?
you may want to take a look at deleteUser() in http://www.anujgakhar.com/2012/02/20/using-rest-services-in-coldfusion-10/ as an example of how to support DELETE in REST API style.
remote any function deleteUser(numeric userid restargsource="Path") httpmethod="DELETE" restpath="{userid}"
{
var response = "";
var qry = new Query();
var userQry = "";
qry.setSQl("delete from tbluser where id = :userid");
qry.addParam(name="userid", value="#arguments.userid#", cfsqltype="cf_sql_numeric");
userQry = qry.execute().getPrefix();
if(userQry.recordcount)
{
response = "User Deleted";
} else {
throw(type="Restsample.UserNotFoundError", errorCode='404', detail='User not found');
}
return response;
}
As for the 2nd part of your question, it'd be best to first turn a query into a array of structs first unless you're using CF11 which does it for you. See: http://www.raymondcamden.com/index.cfm/2014/5/8/ColdFusion-11s-new-Struct-format-for-JSON-and-how-to-use-it-in-ColdFusion-10
The default JSON structure for query in CF 8 to 10 were designed for <cfgrid> in ColdFusion on top of Adobe's discontinued Spry framework.

What's the best way to handle a REST API's 'create' response in Backbone.js

I'm using backbone.js to interact with a REST API that, when posting to it to create a new resource, responds with a status of 201, a 'Location' header pointing to the resource's URI, but an empty body.
When I create a new model at the moment, its successful, but the local representation of the model only contains the properties I explicitly set, not any of the properties that would be set on the server (created_date, etc.)
From what I understand, Backbone would update its representation of the model with data in the body, if there were any. But, since there isn't, it doesn't.
So, clearly, I need to use the location in the Location header to update the model, but what's the best way to do this.
My current mindset is that I would have to parse the url from the header, split out the id, set the id for the model, then tell the model to fetch().
This seems really messy. Is there a cleaner way to do it?
I have some influence over the API. Is the best solution to try to get the API author to return the new model as the body of the response (keeping the 201 and the location header as well)?
Thanks!
Sounds like you will have to do a little customization.
Perhaps override the parse method and url method of your model class inherited from
Backbone.Model.
The inherited functions are:
url : function() {
var base = getUrl(this.collection);
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},
parse : function(resp) {
return resp;
},
and you could try something like:
parse: function(resp, xhr) {
this._url = xhr.getResponseHeader('location')
return resp
}
url: function() {
return this._url
}
Yes, backbone.js really wants the result of a save (be it PUT or POST) to be a parseable body which can be used to update the model. If, as you say, you have influence over the API, you should see if you can arrange for the content body to contain the resource attributes.
As you point out, its makes little sense to make a second over-the-wire call to fully materialize the model.
It may be that a status code of 200 is more appropriate. Purists may believe that a 201 status code implies only a location is returned and not the entity. Clearly, that doesn't make sense in this case.
With Backbone 0.9.9, I couldn't get the accepted answer to work. The signature of the parse function seems to have changed in an older version, and the xhr object is no longer available in the function signature.
This is an example of what I did, to make it work with Backbone v0.9.9 and jQuery 1.8.3 (using a Deferred Object/Promise), relying on the jqXHR object returned by Backbone.Model.save() :
window.CompanyView = Backbone.View.extend({
// ... omitted other functions...
// Invoked on a form submit
createCompany: function(event) {
event.preventDefault();
// Store a reference to the model for use in the promise
var model = this.model;
// Backbone.Model.save returns a jqXHR object
var xhr = model.save();
xhr.done(function(resp, status, xhr) {
if (!model.get("id") && status == "success" && xhr.status == 201) {
var location = xhr.getResponseHeader("location");
if (location) {
// The REST API sends back a Location header of format http://foo/rest/companys/id
// Split and obtain the last fragment
var fragments = location.split("/");
var id = fragments[fragments.length - 1];
// Set the id attribute of the Backbone model. This also updates the id property
model.set("id", id);
app.navigate('companys/' + model.id, {trigger: true});
}
}
});
}
});
I did not use the success callback that could be specified in the options hash provided to the Backbone.Model.save function, since that callback is invoked before the XHR response is received. That is, it is pointless to store a reference to the jqXHR object and use it in the success callback, since the jqXHR would not contain any response headers (yet) when the callback is invoked.
Another other to solve this would be to write a custom Backbone.sync implementation, but I didn't prefer this approach.

How to construct a REST API that takes an array of id's for the resources

I am building a REST API for my project. The API for getting a given user's INFO is:
api.com/users/[USER-ID]
I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?
If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?id=id1,id2,id3,id4,id5
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.
RESTful attempt:
POST http://example.com/api/batchtask
[
{
method : "GET",
headers : [..],
url : "/users/id1"
},
{
method : "GET",
headers : [..],
url : "/users/id2"
}
]
Server will reply URI of newly created batchtask resource.
201 Created
Location: "http://example.com/api/batchtask/1254"
Now client can fetch batch response or task progress by polling
GET http://example.com/api/batchtask/1254
This is how others attempted to solve this issue:
Google Drive
Facebook
Microsoft
Subbu Allamaraju
I find another way of doing the same thing by using #PathParam. Here is the code sample.
#GET
#Path("data/xml/{Ids}")
#Produces("application/xml")
public Object getData(#PathParam("zrssIds") String Ids)
{
System.out.println("zrssIds = " + Ids);
//Here you need to use String tokenizer to make the array from the string.
}
Call the service by using following url.
http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76
where
http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76
As much as I prefer this approach:-
api.com/users?id=id1,id2,id3,id4,id5
The correct way is
api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5
or
api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5
This is how rack does it. This is how php does it. This is how node does it as well...
There seems to be a few ways to achieve this. I'd like to offer how I solve it:
GET /users/<id>[,id,...]
It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.
I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).
I'm interested in comments in my hunt for the ideal solution to this form :)
You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON.
An example controller function would be:
public JsonpResult GetUsers(string userIds)
{
var values = JsonConvert.DeserializeObject<List<int>>(userIds);
var users = _userRepository.GetAllUsersByIds(userIds);
var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
var result = new { users = collection };
return this.Jsonp(result);
}
public IQueryable<User> GetAllUsersByIds(List<int> ids)
{
return _db.Users.Where(c=> ids.Contains(c.Id));
}
Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.
function GetUsers()
{
var link = '<%= ResolveUrl("~")%>users?callback=?';
var userIds = [];
$('#multiselect :selected').each(function (i, selected) {
userIds[i] = $(selected).val();
});
$.ajax({
url: link,
traditional: true,
data: { 'userIds': JSON.stringify(userIds) },
dataType: "jsonp",
jsonpCallback: "refreshUsers"
});
}