How to convert List<List<Map<String, String>>> into List<List<CustomObject>> in dart - dart

I want to convert a List<List<Map<String, String>>> into List<List> a custom class, how to achieve this in dart.
How to convert this
List<List<Map<String, String>>> = [
{
"course_name": "Estimation & Quantity Surveying",
"credit": "4",
"hours": "40",
},
{
"course_name": "IDP - Industrial Design Project phase II",
"credit": "4",
"hours": "40",
}
],
[
{
"course_name": "Data Base Management System",
"credit": "4",
"hours": "40",
},
{
"course_name": "Estimation & Quantity Surveying",
"credit": "4",
"hours": "40",
},
],
];
into
List<List<StudentTimeTable>>
This is my custom class
class StudentTimeTable{
final String courseName;
final String credit;
final String hours;
}

Something like this would do the trick:
class StudentTimeTable {
final String courseName;
final String credit;
final String hours;
StudentTimeTable.fromMap(Map<String, String> map)
: courseName = map['course_name'],
credit = map['credit'],
hours = map['hours'];
#override
String toString() =>
'StudentTimeTable(courseName = $courseName, credit = $credit, hours = $hours)';
}
void main() {
List<List<Map<String, String>>> input = [
[
{
"course_name": "Estimation & Quantity Surveying",
"credit": "4",
"hours": "40",
},
{
"course_name": "IDP - Industrial Design Project phase II",
"credit": "4",
"hours": "40",
}
],
[
{
"course_name": "Data Base Management System",
"credit": "4",
"hours": "40",
},
{
"course_name": "Estimation & Quantity Surveying",
"credit": "4",
"hours": "40",
},
],
];
List<List<StudentTimeTable>> output = [
...input.map(
(subList) => [...subList.map((map) => StudentTimeTable.fromMap(map))])
];
output.forEach(print);
// [StudentTimeTable(courseName = Estimation & Quantity Surveying, credit = 4, hours = 40), StudentTimeTable(courseName = IDP - Industrial Design Project phase II, credit = 4, hours = 40)]
// [StudentTimeTable(courseName = Data Base Management System, credit = 4, hours = 40), StudentTimeTable(courseName = Estimation & Quantity Surveying, credit = 4, hours = 40)]
}
Explanation of what going on!
The solution makes use of "spread operator" which you can read more about here:
https://dart.dev/guides/language/language-tour#spread-operator
In shot, it is a easy way to create a new list and take all elements in an iterable and put into the list.
So lets see what I do:
List<List<StudentTimeTable>> output = [...input.map((subList) => ...)]
Here we define a new list which are filled with the elements from input.map. The map method are used to take each element in the input and convert it to something else. In our case we want to convert each element in our input (which are also a List) from List<Map<String, String>> to List<StudentTimeTable>
We are then mapping each List<Map<String, String>> to the value from this:
[...subList.map((map) => StudentTimeTable.fromMap(map))]
Which returns a list filled with the elements from the iterator returned from subList.map. The purpose of this map is to convert Map<String, String> into StudentTimeTable.
This is done by calling our new constructor which takes a Map<String, String>:
StudentTimeTable.fromMap(Map<String, String> map)
: courseName = map['course_name'],
credit = map['credit'],
hours = map['hours'];
The same code could have been written something like this which is properly easier to read:
final output = <List<StudentTimeTable>>[];
for (final sublist in input) {
final studentTimeTableSubList = <StudentTimeTable>[];
for (final map in sublist) {
studentTimeTableSubList.add(StudentTimeTable.fromMap(map));
}
output.add(studentTimeTableSubList);
}
And a third way would be something like this which uses "collection for" from the same link about "spread operator":
final output = [
for (final sublist in input)
[for (final map in sublist) StudentTimeTable.fromMap(map)]
];

Related

needs to convert Lists of map data into One map

My question is about dart....
the result I got
[{'sam': 8}, {'john': 822}]
I need to convert it into like below
{'sam': 8, 'john': 822}
pls help me.
thanks for reading
Something like this?
void main() {
final listOfMaps = [
{'sam': 8},
{'john': 822},
];
final map = {for (final map in listOfMaps) ...map};
print(map); // {sam: 8, john: 822}
}
Update after example of data has been uploaded
I have made the following example which parses the input you have posted as returns the expected data:
void main() {
final map = {
for (final map in someListOfMaps)
for (final voted in map['voted']! as List<Map<String, String>>)
for (final vote in voted.entries) vote.key: int.parse(vote.value)
};
print(map);
// {60e6956078fb6f42da: 1, 60e6956020d8bf42db: 5, 120d8bf42dffsww66: 1, jd58466daa4dw2: 20, gg4c577x6ad8ds6a: 6}
}
const someListOfMaps = [
{
"voted": [
{"60e6956078fb6f42da": "1"},
{"60e6956020d8bf42db": "5"}
],
"_id": "60e698fe78fb6120d8bf42dd",
"name": "donald"
},
{
"voted": [
{"120d8bf42dffsww66": "1"}
],
"_id": "60e698fe78fb6120d8bf42de",
"name": "barrack"
},
{
"voted": [
{"jd58466daa4dw2": "20"}
],
"_id": "60e698fe78fb6120d8bf42df",
"name": "malan"
},
{
"voted": [
{"gg4c577x6ad8ds6a": "6"}
],
"_id": "60e698fe78fb6120d8bf42e0",
"name": "kuma"
}
];
This is a longer approach and probably more understandable.
// the result I got [{'sam': 8}, {'john': 822}]
// I need to convert it into like below {'sam': 8, 'john': 822}
void main() {
final mapList = [{'sam': 8}, {'john': 822}];
print(mapListToJustMap(mapList)); // output: {sam: 8, john: 822}
// The <int> is not required
print(genericMapListToJustMap<int>(mapList)); // output: {sam: 8, john: 822}
}
Map<String, int> mapListToJustMap(List<Map<String, int>> mapList) {
// Create a new empty map object
final newMap = <String, int>{};
// Iterate through the mapList input
for (final singleMap in mapList) {
// add the current iteration to the new map object
newMap.addAll(singleMap);
}
return newMap;
}
// A generic approach
Map<String, T> genericMapListToJustMap<T>(List<Map<String, T>> mapList) {
// Create a new empty map object
final newMap = <String, T>{};
// Iterate through the mapList input
for (final singleMap in mapList) {
// add the current iteration to the new map object
newMap.addAll(singleMap);
}
return newMap;
}

toJson() invalid when recursively encode tree data structure

I have a Dart class that I am using as a node class for a tree data structure.
My goal here is to encode objects of this class and its child nodes recursively.
I have a toJson() method that takes the child Nodes List and calls jsonencode on them.
class Node{
String name;
Map<String, String> attributes;
List<Node> children = List<Node>();
Node(this.name, attributes) {
this.attributes = attributes;
this.children = List<Node>();
}
Node.fromJson(Map<dynamic,dynamic> _map) {
this.name = _map['name'];
this.children = new List<Node>();
this.attributes = _map['attributes'][0];
for(var i = 0; i < _map['children'].length;i++){
Node temp = new Node.fromJson(_map['children'][i]);
this.addChild(temp);
}
}
Map<String, dynamic> toJson() => {
'name': name,
'attributes': [attributes],
'children': [
...this.children.map(jsonEncode)
]
};
}
I have a unit test i created to test this functionality:
Node nodeMap = {
"name": "Name",
"attributes": [
{"#htag1": "tagval1"}
],
"children": [
{
"name": "NameChild1",
"attributes": [
{"#htag2": "tagval2"}
],
"children": []
},
{
"name": "NameChild2",
"attributes": [
{"#htag3": "tagval3"}
],
"children": []
}
]
};
UNode unodeInst = new UNode.fromJson(nodeMap);
// Act
var nodeCreate = nodeInst.toJson();
// Assert
expect(nodeCreate, equals(nodeMap));
Here is the output of my unit test
Expected: {
'name': 'Name',
'attributes': [{'#htag1': 'tagval1'}],
'children': [
{
'name': 'NameChild1',
'attributes': [{'#htag2': 'tagval2'}],
'children': []
},
{
'name': 'NameChild2',
'attributes': [{'#htag3': 'tagval3'}],
'children': []
}
]
}
Actual: {
'name': 'Name',
'attributes': [{'#htag1': 'tagval1'}],
'children': [
'{"name":"NameChild1","attributes":[{"#htag2":"tagval2"}],"children":[]}',
'{"name":"NameChild2","attributes":[{"#htag3":"tagval3"}],"children":[]}'
]
}
Which: at location ['children'][0] is '{"name":"NameChild1","attributes":[{"#htag2":"tagval2"}],"children":[]}' which expected a map
As you see its not encoding my object correctly.
I believe this is happening because when i reclusively call jsonencode this method returns a string that is placed into the children array.
I believe part of my problem is that i dont fully understand the d diffrence between jsonencode() and toJson().
It is my understanding that jsonencode() calls toJson().. but jsonencode() returns a string and toJson() returns a Map<String, dynamic>.. so i think what i want here is to call toJson() recursively and not jsonencode.
Does this sound correct?
But i cannot figure out how to do this on a list in this situation.
I have tried the following
...this.children.map(this.toJson())
but i get "The argument type 'Map<String, dynamic>' can't be assigned to the parameter type 'dynamic Function(Node)'"
...this.children.forEach((element) {element.toJson()})
but i get "Spread elements in list or set literals must implement 'Iterable'"
Does this mean i have to implement the Iterable interface in my class?
You're just using the map method incorrectly. Use the following instead.
[
...this.children.map((e) => e.toJson())
]
It's also unnecessary to use spread with a literal list or use this. You can simplify the code to just
children.map((e) => e.toJson()).toList()

Grab test's pass/fail from TestCase via TFS Rest API

I'm trying to grab the Outcome off of a testcase in TFS, looks something like this.
and I can't seem to find a straightforward way to do it. I've tried to grab the workitem directly, query for the property with no success. I was able to use the SDK to get the data (which I'm trying to avoid)
_tfs = new TfsTeamProjectCollection(new Uri(website)) { ClientCredentials = what };
_tfs.EnsureAuthenticated();
var testService = _tfs.GetService<ITestManagementService>();
var aPoint = plan.QueryTestPoints("SELECT * FROM TestPoint WHERE TestCaseId = 10").SingleOrDefault();
console.Write(aPoint.MostRecentResultOutcome);
I have the ID for the testcase from the webhook so that's not a problem. All I want is that "MostRecentResultOutcome". Is there a way to get that data from the REST api in 1 call?
You could also use below REST API which will return a list of test points through test case ID according to your code info:
GET https://Fabrikam-Fiber-inc.VisualStudio.com/DefaultCollection/fabrikam-fiber-tfvc/_apis/test/plans/1/suites/1/points?testcaseid=39&api-version=1.0
Then will get a response with lastTestRun, lastResutl, outcome...
{
"value": [
{
"id": 1,
"url": "https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/fabrikam-fiber-tfvc/_apis/test/Plans/1/Suites/1/Points/1",
"assignedTo": {
"id": "d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
"displayName": "Jamal Hartnett"
},
"configuration": {
"id": "2",
"name": "Windows 8"
},
"lastTestRun": {
"id": "28"
},
"lastResult": {
"id": "100000"
},
"outcome": "Passed",
"state": "Completed",
"testCase": {
"id": "39",
"url": null,
"webUrl": null
},
"workItemProperties": [
{
"workItem": {
"key": "Microsoft.VSTS.TCM.AutomationStatus",
"value": "Not Automated"
}
}
]
}
],
"count": 1
}
As Patrick said, you can't as of right now. What I ended up doing its grabbing the ID and System.TeamProject off of the webhook passing that along as such
private TfsTeamProjectCollection _tfs;
private ITestManagementTeamProject _project;
private readonly ITestManagementService _service;
public TfsThing(string instanceUrl, string user, string password)
{
var cred = new VssBasicCredential(user, password);
_tfs = new TfsTeamProjectCollection(new Uri(instanceUrl)) { ClientCredentials = cred };
_tfs.EnsureAuthenticated();
_service = _tfs.GetService<ITestManagementService>();
}
public string GetTestStatus(int id, string projectName)
{
var project = _service.GetTeamProject(projectName);
var result = project.TestResults.ByTestId(id);
return result.LastOrDefault()?.Outcome.ToString();
}
This was the shortest way I found -- may not be the most efficient though
Incase you were wondering, these are the two packages I used
Install-Package Microsoft.TeamFoundationServer.Client
Install-Package Microsoft.TeamFoundationServer.ExtendedClient

Using a list from JSON in MVC

I am using a Utilities.Cache.Insert to insert the JSON output from a URI.
[
{
Id": 44,
"Address": "nho:87, Huston",
"Name": "Ann"
},
{
"Id": 87,
"Address": "nho:17, Texas",
"Name": "Robert"
}
...
...
]
Utilities.Cache.Insert("my_list", AddList);
Then using a "SelectListItem" List to store the "Name" and "Address"
List<SelectListItem> d = new List<SelectListItem>();
foreach (Dictionary<string, string> item in AddList)
{
d.Add(new SelectListItem() { Text = item["Name"], Value = item["Address"] });
}
However, I need a way to store all three values, "Name","Address" and "Id" so "selectListItem" cannot be used. What are the other alternatives?

How to access URI query parameters from a Resource class using Apigility?

I'm developing an Apigility driven application based on the Zend Framework 2.
I want my application to provide nested responses for both -- single items and lists:
/projects/1
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
},
{
"id": "2",
"project_id": "1",
"title": "...",
...
}
]
},
...
}
/projects
{
...
"_embedded": {
"projects": [
{
"id": "1",
"title": "...",
...
"_embedded": {
"images": [
{
"id": "1",
"project_id": "1",
"title": "...",
...
},
...
]
},
...
},
...
]
},
"total_items": 2
}
Since I've not found an apigility conform solution for implementing lists with nested lists (in this case projects with a list of images for every project list item, see here). I have to deal with the Paginator and DbAdapter and provide the page parameter manually:
class ProjectResource extends AbstractResourceListener {
...
public function fetchAll($params = array()) {
$pageNumber = $this->getEvent()->getRouteMatch()->getParam('page', 1); <-- that doesn't work
$projectService = $this->getProjectService();
$offset = $pageNumber > 0 ? $pageNumber - 1 : 0;
$config = $this->getServiceManager()->get('Config');
$itemCountPerPage = $config['zf-rest']['Portfolio\\V2\\Rest\\Project\\Controller']['page_size'];
$projects = $projectService->getProjects($offset, $itemCountPerPage);
return $projects;
}
...
}
The problem is, that $this->getEvent()->getRouteMatch()->getParam('page', 1) doesn't work. Instead of the page parameter, $this->getEvent()->getRouteMatch()->getParams() returns
Array
(
[controller] => Portfolio\V2\Rest\Project\Controller
[version] => 2
)
How to access request parameters?
Request parameters have first to be added onto the whitelist. It can be done over the Apigility GUI or directly in the config:
module.config.php
return array(
...
'zf-rest' => array(
...
'Portfolio\\V2\\Rest\\Project\\Controller' => array(
...
'collection_query_whitelist' => array('page'),
...
),
...
),
);
Then the parameter can be accessed over the arguments of the end point methods of the Resource class:
public function fetchAll($params = array()) {
$projectService = $this->getProjectService();
$config = $this->getServiceManager()->get('Config');
$itemCountPerPage = $config['zf-rest']['Portfolio\\V2\\Rest\\Project\\Controller']['page_size'];
$pageNumber = isset($params['page']) && intval($params['page']) > 0
? $params['page']
: 1
;
$offset = ($pageNumber - 1) * $itemCountPerPage;
$projects = $projectService->getProjects($offset, $itemCountPerPage);
return $projects;
}
See also the Apiglity documentation: ZF REST -> Configuration -> User Configuration -> collection_query_whitelist.

Resources