Decoding Multiple JSON URLs into a Single Class - ios

I'm attempting to decode multiple JSON URLs into a class. Since I'm using an API, I have no control over the fact that the JSON data is split into two URLs. Here is the problem statement:
I have a class called Student
JSON URL student_info.json contains a dictionary with all students and the Student instance constants A, and B.
JSON URL student_status.json contains Student instance variables C, D, and E.
I need to do the following:
Retrieve the dictionary of students from student_info.json to populate a collection of Students and instantiate them with attributes A and B.
Save this Student collection so that it is accessible throughout the rest of the app's lifecycle.
Retrieve the dictionary of student information from student_status.json and populate Student instance variables C, D, and E for each student in the collection.
From time to time, update the collection of students (in case any were dropped or added).
From time to time, update variables C, D, and E for each student in the collection.
Here are some example files:
File:
student_info.json
Content:
{
"last_updated": 1535936693,
"tyl": 10,
"data": {
"students": [
{
"student_id": "1",
"name": "John Appleseed",
},
{
"student_id": "2",
"name": "Jane Doe"
}
]
}
}
File:
student_status.json
Content:
{
"last_updated": 1535936693,
"tyl": 10,
"data": {
"students": [
{
"student_id": "1",
"number_of_classes": "10",
"GPA": "2.87",
"tuition_due": "237.33"
},
{
"student_id": "2",
"number_of_classes": "10",
"GPA": "2.87",
"tuition_due": "237.33"
}
]
}
}
File
Student.swift
Content
class Student {
var student_id: Int
var name: String
var numberOfClasses: Int?
var gpa: Double?
var tuitionDue: Double?
}

Related

OData GroupBy and Select

Expecting the following example table CustomerOrders
Id
CustomerId
Customer
Product
1
1
Alice
Pizza
2
1
Alice
Pasta
3
2
Bob
Burger
In C# I'm was able to use the following Linq query to produce a nice List<Customer> result with a nested orders collection for every customer:
List<CustomerOrders> queryResult = GetCustomerOrders();
return queryResult
.GroupBy(x => x.CustomerId)
.Select(x => new Customer
{
Id = x.First().CustomrId,
Customer = x.First().Customer,
Orders = x.ToList()
})
.ToList();
Now I want to achive this result directly over an odata query in the client application to get the following JSON result:
[
{
"id": 1,
"customer": Alice,
"orders": [ "Pizza", "Pasta" ]
},
{
"id": 2,
"customer": Bob,
"orders": [ "Burger" ]
}
]
Is there a way to transfer this query in odata?
GroupBy in OData is similar to SQL, only the aggregates and common columns are returned, we lose access to the individual items, so we can return a grouping and a count of the orders, using group by, but not the array of orders.
If your schema has a Customer entity and there is a collection navigation property from Customer to Orders, then we do not need to use grouping at all:
~/Customers?$expand=Orders($select=Product)&$select=Id,Name
The output is structured in a slightly similar manner and should resemble something like this:
{
"#odata.context": "~/$metadata#Customers(Id,Name,Orders(Product))",
"value": [
{
"Id": 1,
"Name": "Alice",
"Orders": [{"Product": "Pizza"},
{"Product": "Pasta"}]
},
{
"Id": 2,
"Name": "Bob",
"Orders": [{"Product": "Burger"}]
}
]
}
A key concept in OData is that the shape of the overall graph should not be modified, it is designed deliberately to always maintain the structure of the Entities that are returned. This means that the definition document is always correct, the only thing missing from this response is the additional fields that were not requested.
If you need the output in the client specifically as mentioned, then you can expose that as a custom function on the controller:
[EnableQuery]
public IQueryable<CustomerSummary> GetCustomersWithOrderSummary()
{
List<CustomerOrders> queryResult = GetCustomerOrders();
return queryResult
.GroupBy(x => x.CustomerId)
.Select(x => new CustomerSummary
{
Id = x.Key,
Customer = x.First().Customer,
Orders = x.Select(o => o.Product)
});
}
If using GroupBy, the closest response we can get is this:
~/CustomerOrders?$apply=groupby((CustomerId,Customer),aggregate($count as Orders))
But here we will return a count of the orders, and not an array of the product values as expected:
{
"#odata.context": "~/$metadata#CustomerOrders(CustomerId,Customer,Orders)",
"value": [
{
"#odata.id": null,
"CustomerId": 1,
"Customer": "Alice",
"Orders": 2
},
{
"#odata.id": null,
"CustomerId": 2,
"Customer": "Bob",
"Orders": 1
}
]
}

Swift Codable not working for array of values

In my case I am trying to get JSON data using codable. Here, I can’t able to get data[Datum] values. How to get it and assign tableview data. I used to generate codable by using quicktype.io
JSON Data
{
"status": true,
"data": [
{
"id": "1",
"name": "one",
"description": "hello",
"date": "2020-08-05 11:37:52",
"startdate": "2019-08-05 11:37:52",
"createdby": "1",
"status": "0"
},
{
"id": "2",
"name": "two",
"description": "hi",
"date": "2020-08-05 11:37:52",
"startdate": "2019-08-05 11:37:52",
"createdby": "1",
"status": "0"
}
]
}
Codable Struct
// MARK: - Welcome
struct Welcome: Codable {
let status: Bool
let data: [Datum]
}
// MARK: - Datum
struct Datum: Codable {
let id, name, datumDescription, date: String
let startdate, createdby, status: String
enum CodingKeys: String, CodingKey {
case id, name
case datumDescription = "description"
case date, startdate, createdby, status
}
}
Code
let id: String = result.data.(Nothing Showing except Description)
let id: String = result.data.(Nothing Showing except Description)
It's not clear what "Nothing Showing except Description" means here, but the syntax you would expect would be:
let id: String = result.data[0].id // The id of the first Datum
data is an Array, so you'll need to subscript or iterate over it to get elements. For a tableview, you'd expect something like:
let id: String = result.data[indexPath.row].id
If this is not what you mean, you need to edit your question to make clear what your actual code is and the specific error message you receive.

get parent object filter by nested child fields

Inside teacher, there is child subject, and subject has a child student. I want to get all teachers filter by student_name. Teacher object can be something like this:
{ "id": 5,
"name": "teacher-one",
"gender": "male",
"subject": {
"id": 10,
"subject_name": "Maths",
"student": {
"id": 1,
"student_name": "student-one",
"grade" : "one",
}
}
}
I am looking to filter this out by using find method, something like
Teacher.find(:all, params: {gender: "male'}) which returns all the male teachers. But the following code does not work:
Teacher.find(:all, params: { subject: { student: grade == "one" }})
Try this:
Teacher.joins(subject: :student).where(student: {student_name: "Bala"})

MagicalRecord map String array to object

I'm using MagicalRecord to import json object to Core Data. I have a list of persons with firstName and lastName attributes. This works fine. each person has a list of degrees that is a simple array of strings. I would like to map this list of string to my Degree core data entity and map the string to the e.g. Degree.name attribute
[
{
"firstName": "ba",
"lastName": "bar",
"degrees": [
"MSc",
"BSc"
]
},
{
"firstName": "Fo",
"lastName": "foo",
"degrees": [
"MSc"
]
}
]
I tried using a empty mappedKeyName on the name attribute as described here but it does not work.

Output JSON array without the class name in every array element

The default way to output JSON in rails is some thing like:
Code:
render :json => friends.to_json(:only => [:username, :avatar_file_name, :id ])
Output
{"friends" :
[{"user":
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1}},
{"user":
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2}},
{"user":
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}}
]}
But i want something like:
{"friends" :
{"user": [
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1},
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2},
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}
]}
}
The class is specified by the array name.
Last.fm also uses this syntax see Last.fm 'API-user.getfriends'
The solution to this problem is commenting the line
ActiveRecord::Base.include_root_in_json = true
in initializers/new_rails_defaults.rb
Or setting ActiveRecord::Base.include_root_in_json to false.
You can use javascript to reformat it:
var json =
{
"friends" :
{ "user": [] }
}
var i = 0;
for ( x in friends )
{
json.friends.user[i].avatar_file_name = x.user.avatar_file_name; // add more fields.
i++;
}
Something among those lines.
JSON is normally used to represent objects in a text format.
So if you like the secon output you must change your objects.
The first output says:
there is a friends object which is a array of user, each user has some properties among which you chose to expose username, avatar_file_name, id
The second output says:
there is a friends object which contains a user object which is an array of unnamed objects, each unnamed objects has some properties...
This second output is not writable in JSON syntax.
It might be:
{"friends" :
{"user": [
["avatar_file_name", "username", "id"],
["image1.jpg", "user1", 1],
["image2.jpg", "user2", 2],
["image3.jpg", "user3", 3]
]}
}
This says:
there is a friends object which contains a user object which is an array of array (a table with field names on first row) ...

Resources