I'm receiving some paginated JSON response through my API that looks something like this:
page 1:
{
"count": 96,
"next": "http://127.0.0.1:8000/id=5/?page=2",
"previous": null,
"results": [
{
"id": 10,
"book_name": "Book name",
"book_id": 70,
"chapter_number": 1,
"verse": "Verse title here",
"verse_number": 1,
"chapter": 96
},
{
"id": 198,
"book_name": "Book Name",
"book_id": 70,
"chapter_number": 8,
"verse": "Text here",
"verse_number": 5,
"chapter": 103
}
]
}
As I move through the paginated result, ie calling: http://127.0.0.1:8000/id=5/?page=2
I'll get new values in the results array.
page 2:
{
"count": 96,
"next": "http://127.0.0.1:8000/id=5/?page=3",
"previous": "http://127.0.0.1:8000/id=5/",
"results": [
{
"id": 206,
"book_name": "Book on Second page",
"book_id": 70,
"chapter_number": 8,
"verse": "yadda yadda",
"verse_number": 13,
"chapter": 103
},
{
"id": 382,
"book_name": "Book on second page..",
"book_id": 70,
"chapter_number": 15,
"verse": "Verse here",
"verse_number": 12,
"chapter": 110
}
]
}
How would I structure my struct/fix my decoding so I can append the values of results from the JSON while still updating count, next and previous as I go through ..?page=3, ..?page=4 etc
Currently, my struct looks like this:
struct VersesSearchResult: Decodable {
var results: [Verse]
var count: Int
var next: String?
var previous: String?
}
When doing the decoding, I'm not sure what the syntax should be like to append results to the struct, and update next, previous, and count. So far I got this
...
let verses = try JSONDecoder().decode(VersesSearchResult, from: safeData)
DispatchQueue.main.async {
// somehow need to get this to work - not entirely sure how
// where results gets appended, while the rest in the JSON values gets updated
// obviously I can't do as below:
self.verseSearchResult.append(contentsOf: verses.results)
self.verseSearchResult = verses
}
...
Decode to a temprary instance of the type, then process those properties into your main instance. Depending how you want to process the data, it'll look something like this
extension VersesSearchResult {
mutating func update(with new: VersesSearchResult) {
results.append(new)
count = new.count
next = new.next
prev = new.prev
}
}
and then in your completion block
let newVerses = try JSONDecoder().decode(VersesSearchResult, from: safeData)
self.verses.update(with: newVerses)
If needs be force the update onto the main thread.
You should also handle failure in the 'try' either with a do...catch or other approach.
Related
I am learning IPFS and trying to save IPFS file info in MongoDB. After uploading, I get one hash value
ex: {fileHash: CID(QmbCaWPi9tSqcnykvBUMaH2M1d5PiVPLEfPwhJksSSeMak)}
And in MongoDB, I see something like this:
"fileHash": {
"code": 112,
"version": 0,
"multihash": {
"code": 18,
"size": 32,
"digest": "vxaISoMOXTpFy9rwnYilyk7pa6TlhkFDCZgcjGhXfm0=",
"bytes": "EiC/FohKgw5dOkXL2vCdiKXKTulrpOWGQUMJmByMaFd+bQ=="
},
"bytes": "EiC/FohKgw5dOkXL2vCdiKXKTulrpOWGQUMJmByMaFd+bQ=="
}
Now I want to update this document based on hash value but don't understand what value I compare in match.
db.collection("test").update(filter, set);
I was trying like this:
db.collection("test").update({fileHash:"CID(QmbCaWPi9tSqcnykvBUMaH2M1d5PiVPLEfPwhJksSSeMak)"}, set);
But it doesn't work
I think CID() is like a function.
When you use CID("QmbCaWPi9tSqcnykvBUMaH2M1d5PiVPLEfPwhJksSSeMak"), it come up with a JSON.
{
"code": 112,
"version": 0,
"multihash": {
"code": 18,
"size": 32,
"digest": "vxaISoMOXTpFy9rwnYilyk7pa6TlhkFDCZgcjGhXfm0=",
"bytes": "EiC/FohKgw5dOkXL2vCdiKXKTulrpOWGQUMJmByMaFd+bQ=="
},
"bytes": "EiC/FohKgw5dOkXL2vCdiKXKTulrpOWGQUMJmByMaFd+bQ=="
}
So you should try something like
let fileHash = CID("QmbCaWPi9tSqcnykvBUMaH2M1d5PiVPLEfPwhJksSSeMak");
db.collection("test").update({fileHash: fileHash }, set);
Take that CID and use the method toString() on it.
i get data from API like demo:-
{draw: 0, records Total: 210, records Filtered: 210, data: [,…], input: []}
data: [,…]
draw: 0
input: []
records Filtered: 210
records Total: 210
I want to apply paggination on API data (grid view or list view)
How can i do that ?
Your json structure needs to look like this to apply pagination with ease.
Use current page, next page and last page to determine the next, current and remaining pages.
You can directly use the next link to get the data of the next page.
{
"meta": {
"page": {
"current-page": 2,
"per-page": 15,
"from": 16,
"to": 30,
"total": 50,
"last-page": 4
}
},
"links": {
"first": "http://localhost/api/v1/posts?page[number]=1&page[size]=15",
"prev": "http://localhost/api/v1/posts?page[number]=1&page[size]=15",
"next": "http://localhost/api/v1/posts?page[number]=3&page[size]=15",
"last": "http://localhost/api/v1/posts?page[number]=4&page[size]=15"
},
"data": [...]
}
I have a map, with multiple layers, some of the layers have an events field which may contain 0 or more event listings inside of it.
Some of events are nested deeper into the map, while others are closer to the top layer.
Here is what the graphql query result looks like:
{
"data": {
"users": [
{
"id": 16,
"friends": [
{
"senderId": 16,
"receiverId": 17,
"userByReceiverid": {
"id": 17,
"events": [],
"friends": [
{
"receiverId": 14,
"userByReceiverid": {
"id": 14,
"events": [
{
"id": 3,
"photoUrl": "none",
"name": "hello",
"date": "1982-06-27",
"startTime": "01:00:00+00",
"endTime": "02:00:00+00",
"fee": "$2.00",
"maxNumber": 10,
"ageRestriction": "none",
"about": "amazing",
"allowShare": false,
"private": false,
"timestamp": "2021-06-26T17:57:13.224383+00:00",
"senderId": 14
}
]
}
},
{
"receiverId": 20,
"userByReceiverid": {
"id": 20,
"events": []
}
}
]
}
}
],
"friendsByReceiverid": [
{
"senderId": 20,
"receiverId": 16,
"user": {
"id": 20,
"events": [],
"friendsByReceiverid": [
{
"receiverId": 20,
"user": {
"id": 14,
"events": [
{
"id": 3,
"photoUrl": "none",
"name": "hello",
"date": "1982-06-27",
"startTime": "01:00:00+00",
"endTime": "02:00:00+00",
"fee": "$2.00",
"maxNumber": 10,
"ageRestriction": "none",
"about": "amazing",
"allowShare": false,
"private": false,
"timestamp": "2021-06-26T17:57:13.224383+00:00",
"senderId": 14
}
]
}
},
{
"receiverId": 20,
"user": {
"id": 17,
"events": []
}
}
]
}
}
]
}
]
}
}
I want to search the Map and make a list that contains all the events that are unique, so no duplicates if possible.
How would I go about pulling out only the events field from a map at any given point?
Essentially what you need is a function (visitObject) that goes through each key of the a Map and recursively calls itself till all properties have been checked.
The function should also check for the possible types it can operate on and handle the data so you can call the visitObject function with the right arguments.
I believe the right data structure here would be a Set. In dart as Set is defined as A collection of objects in which each object can occur only once.
However Set a set falls back to the dart method of equality which is the == operator, so you would either need to use a calls for Events or use a package like BuiltValue which will generate the == operator for your value types.
Here is an example that can help you get started, I have left equality checking for you to determine what best and how you want to apply it.
final Set<Map<String, dynamic>> items = {};
void main() {
visitObject(data);
}
void visitObject(object) {
if (object is List) {
for(dynamic item in object) {
visitObject(item);
}
} else if (object is Map) {
if (object.containsKey('events')) {
var _events = object['events'];
if (_events is List && _events.isNotEmpty) {
_events.forEach((e) {
if (!items.contains(e)) {
items.add(e);
}
});
}
}
for (dynamic item in object.values) {
visitObject(item);
}
}
}
Additional Reading for equality:
==Operator
hashCode
BuiltValue
I have two lists and I want to make a new list by comparing the two lists and the new list should only contain those elements that contain in each of them.
List1=[[id: 1, label: 'cocoa'],[id: 2, label: 'apple'],[id: 3, label: 'cherry'],[id: 4, label: 'banana'],[id: 5, label: 'melon'],[id: 6, label: 'orange'],[id: 7, label: 'pineapple'],[id: 8], label: 'strawberry']
List2=[2,5,7,8]
expectedList = [[id: 2, label: 'apple'],[id: 5, label: 'melon'],[id: 7, label: 'pineapple'],[id: 8], label: 'strawberry']]
And the real code down below:
"options": [
{
"id": 58,
"label": "cocoa",
"swatch_value": null,
"products": [
118
]
},
{
"id": 59,
"label": "dark chocolate",
"swatch_value": null,
"products": [
120,
127
]
},
{
"id": 60,
"label": "apple",
"swatch_value": null,
"products": [
121,
128
]
},
{
"id": 61,
"label": "milk",
"swatch_value": null,
"products": [
122
]
},
{
"id": 62,
"label": "coconut",
"swatch_value": null,
"products": [
130
]
},
{
"id": 65,
"label": "cherry",
"swatch_value": null,
"products": [
126
]
}
]
So the first list would contain the json above, and the second list contains the numbers below that equals to some of the ID.
List<int> secondList = [58, 59, 60, 61];
Now when I want to generate a new list by comparing the secondList with the ID's of the first list, the third list is empty.
List thirdList = firstList.options.where((element) => secondList.contains(element.id)).toList();
var list1 = [1,2,3,4,5,6,7,8];
var list2 = [2,5,7,8];
var expectedList = list1.toSet().intersection(list2.toSet()).toList();
print(expectedList.toString());
More information here.
Respect to your info:
var dataList = data['options'];
var firstList = List<int>.generate(dataList.length, (i) => dataList[i]['id']);
var secondList = [58, 59, 60, 61];
var thirdList = firstList.toSet().intersection(secondList.toSet()).toList();
var filtered = dataList.where((e) => thirdList.contains(e['id'])).toList();
print(filtered.toString());
where:
const data = {
"options": [
...
]
};
The result is:
[{id: 58, label: cocoa, swatch_value: null, products: [118]}, {id: 59, label: dark chocolate, swatch_value: null, products: [120, 127]}, {id: 60, label: apple, swatch_value: null, products: [121, 128]}, {id: 61, label: milk, swatch_value: null, products: [122]}]
In Gatling using scala scripting.. I need to extract choiceId's for each question according to the questionTypes and questionId's from the previous response and submit one choice randomly in the next API call.
From an API_01 of the response I am saving the questionTypes, questionId's and also saving the whole response data in Resp using json path.
Now according using he no. of question ID's which is an array the loop iterates (if 4 question Id's then there are 4 question types and ll iterate 4 times) and also checks the question type for each iteration and switch is used to perform the function according to the question type.
After going inside the question type I need to answer for which I need ChoiceId's which will differ from question to question (which will have 3 choices or 2 choices or 5 choices)
So I have saved the whole response in the previous API_01 call now I need to extract it and add to API_02 call POST request json file; I have QuestionId and QuestionType
API_01 to get the questionID, questionType and ChoiceID
private val Assessment = exec(http("assessment")
.post("/Test-graphql")
.headers(commonHeaders)
.body(ElFileBody("/createAssessment.json"))
.check(jsonPath("""$.data.assessment.items[*].question.id""").findAll.saveAs("questionIds"))
.check(jsonPath("""$.data.assessment.items[*].question.type""").findAll.saveAs("questionType"))
.check(jsonPath("""$.data.assessment""").findAll.saveAs("ResponseData"))
)
Response of Above API Call
{
"data": {
"assessment": {
"id": "sample01",
"items": [
{
"question": {
"id": "sample02",
"code": "E_01",
"version": 1,
"type": "MULTIPLE_SELECTION",
"language": "E",
"body": {
"choices": {
"minChoice": 1,
"maxChoice": 7,
"choiceItems": [
{
"choiceId": 2, --> How to get these choiceID for answer Submission
},
{
"choiceId": 3, --> How to get these choiceID
},
{
"choiceId": 115, --> How to get these choiceID
},
{
"choiceId": 196, --> How to get these choiceID
}
]
},
},
},
"submissions": [
],
},
{
"question": {
"id": "sample02",
"code": "E_01",
"version": 1,
"type": "FILL_IN_THE_BLANK",
"language": "E",
"body": {
"choices": {
"minChoice": 1,
"maxChoice": 7,
"choiceItems": [
{
"choiceId": 20, --> How to get these choiceID
},
{
"choiceId": 15,
},
{
"choiceId": 11,
},
{
"choiceId": 156,
}
]
},
},
},
"submissions": [
],
}
]
} } }
Method during Answer submission:
private val Answers = foreach("${questionId}", "id","i") {
doSwitch("${questionTypes(i)}")(
"MULTIPLE_CHOICE" -> answerMCQ,
"MULTIPLE_SELECTION" -> answerMSQ
"FILL_IN_THE_BLANK" -> answerFIB
)
Sample Answer Function
private val answerFIB = exec(
http("Submit Answer")
.post("/submitanswer-grapql")
.headers(commonHeaders)
.body(ElFileBody("data/AnswerFIB.json"))
.check(status.is(200))
.check(jsonPath("$.data.assessmentAnswerSubmit.id").is("${assessmentId}"))
)
Sample AnswerFIB.json for answer submission:
"answer": {
"ChoiceId": 354,--> Here I need to provide Choice ID which changes for each question answer
"answer": "Sample01",
"type": "FILL_IN_THE_BLANK"
}