How to achieve this format in swift? - swift

I want to pass a parameter in my POST method. This is the valid parameter to be sent.
{
"feedback" : "Sample Feedback",
"orderId" : 1240,
"ratings" : [
{
"rateType" : 1,
"rating" : 3
},
{
"rateType" : 2,
"rating": 4
}
],
"sellerId" : 598,
"title" : "Sample title"
}
I am using this(below) to achieve that format(above) but the server returns invalid feedback. Please help me if I'm missing something or doing wrong to achieve the format above.
let parameter: [String: AnyObject] = [
"sellerId": self.sellerId,
"orderId": self.orderId,
"title": "Seller Feedback",
"feedback": "Sample Feedback",
"ratings": [[
"rateType": 1,
"rating": self.rate1
], [
"rateType": 2,
"rating": self.rate2
]]
]
Thank you!

Dictionaries are not ordered. you'll have to implement your own ordered dictionary or use a struct. here is one from http://timekl.com/blog/2014/06/02/learning-swift-ordered-dictionaries/
struct OrderedDictionary<Tk: Hashable, Tv> {
/* ... vars and init ... */
subscript(key: Tk) -> Tv? {
get {
return self.values[key]
}
set(newValue) {
if newValue == nil {
self.values.removeValueForKey(key)
self.keys.filter {$0 != key}
return
}
let oldValue = self.values.updateValue(newValue!, forKey: key)
if oldValue == nil {
self.keys.append(key)
}
}
}
}

Related

Using MongoDB $set to update multiple subdocuments

I have such Article-documents:
{
"_id" : "rNiwdR8tFwbTdr2oX",
"createdAt" : ISODate("2018-08-25T12:23:25.797Z"),
"title" : "Happy",
"lines" : [
{
"id" : "5efa6ad451048a0a1807916c",
"text" : "Test 1",
"align" : "left",
"indent" : 0
},
{
"id" : "ae644f39553d46f85c6e1be9",
"text" : "Test 2"
},
{
"id" : "829f874878dfd0b47e9441c2",
"text" : "Test 3"
},
{
"id" : "d0a46ef175351ae1dec70b9a",
"text" : "Test 4"
},
{
"id" : "9bbc8c8d01bc7029220bed3f",
"text" : "Test 5"
},
{
"id" : "6b5c02996a830f807e4d8e35",
"text" : "Test 6",
"indent" : 0
}
]
}
I need to update some Lines.
For example I have array with ids of the line which must be updated.
let lineIds = [
"5efa6ad451048a0a1807916c",
"829f874878dfd0b47e9441c2",
"6b5c02996a830f807e4d8e35"
];
So I try to update attributes "attr" for the "lines" and I do following:
'articles.updateLines': function (articleId, lineIds, attr, value) {
return Articles.update({
'_id': articleId,
'lines.id': { $in: lineIds }
},
{
$set: {
['lines.$.' + attr]: value
}
},
{ multi: true }
);
}
The problem is that just the first line (with id="5efa6ad451048a0a1807916c") is updated.
Any ideas? Thanks! :)
You can use $[]. This will works only MongoDB version 3.6 and above.
Refer link :
https://docs.mongodb.com/manual/reference/operator/update/positional-all/
You can also see this stackoverflow question reference:
How to add new key value or change the key's value inside a nested array in MongoDB?
You can convert below query in your function
db.col.update(
{ '_id':"rNiwdR8tFwbTdr2oX", },
{ $set: { "lines.$[elem].text" : "hello" } },
{ arrayFilters: [ { "elem.id": { $in: lineIds } } ],
multi: true
})
'lines.id': { $in: lineIds }
This won't work, because lines is an array.
What I understand from your question, you can prepare a new array with proper processing and replace the lines array with the new one. Here is an idea how to do this:
'articles.updateLines': function (articleId, lineIds, attr, value) {
let lines = Articles.findOne(articleId).lines;
// prepare a new array with right elements
let newArray = [];
for(let i=0; i<lines.length; i++){
if(lineIds.includes(lines[i].id)){
newArray.push(value)
}
else newArray.push(lines[i])
}
return Articles.update({
'_id': articleId,
},
{
$set: {
lines: newArray
}
}
);
}

Fetch all relationship data - Core Data

I am new to core data. I am fetching data from API and then saving them to core data.This is my dataModel.
Here is my API Structure,
{
"name" : "name here",
"content" :[
{
"homeContentItems" : [
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
},
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
}
]
},
{
"homeContentItems" : [
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
},
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
}
]
}
]
}
How can I fetch data from the Entity so I can get all data from related entity too?
I Have never worked with database before so its bit complected for me. Any help will be much appreciated.
let informedDataFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Informed360Entity")
informedDataFetch.fetchLimit = 1
informedDataFetch.predicate = NSPredicate()
let tableviewData = try! context.fetch(informedDataFetch)
let tdata : Informed360Entity = tableviewData.first as! Informed360Entity
var contentData = tdata.toContent?.allObjects as? [ContentEntity]
I tried this code and getting data from ContentEntity table. How can I get other 2 tables data too so I can use to display in tableview.
You do it the same way as you did with ContentEntity but now you use the two properties that represent the relationships, contentDetailItem and homeContentItems, which both will return a Set.
for content in contentData {
let contentDetailItems = content.contentDetailItem
let homeContents = content.homeContentItems
//...
}

Type Mismatch with Decodable and Object

I've got a problem with parsing data from the server. I've got JSON which has an array of objects, something like this:
{
"items": [
{
"itemType": {
"id": 12,
"tagId": "FCHA78558D"
},
"parts": [
{
"partId": 52,
"manufacturer": "xxx"
},
{
"partId": 53,
"manufacturer": "xxx"
},
{
"partId": 54,
"manufacturer": "xxx"
}
],
"description": "yyy"
},
{
"itemType": {
"id": 13,
"tagId": "FCHA755158D"
},
"parts": [
{
"partId": 64,
"manufacturer": "xxx"
},
{
"partId": 65,
"manufacturer": "xxx"
}
],
"description": "zzz"
}
]
}
I only want to obtain this one array of objects so I implemented this class like this:
class User : Object, Decodable {
var items = List<Equipment>()
}
in the Alamofire I'm downloading the JSON, parsing it to data and then in do-catch block I receive an error:
let items = try JSONDecoder().decode(User.self, from: receivedValue)
error:
▿ DecodingError
▿ typeMismatch : 2 elements
- .0 : Swift.Array<Any>
▿ .1 : Context
▿ codingPath : 2 elements
- 0 : CodingKeys(stringValue: "items", intValue: nil)
▿ 1 : _JSONKey(stringValue: "Index 0", intValue: 0)
- stringValue : "Index 0"
▿ intValue : Optional<Int>
- some : 0
- debugDescription : "Expected to decode Array<Any> but found a dictionary instead."
- underlyingError : nil
That's weird because it is an array of objects for sure. I tried setting my items property to String to see the result and then I got:
- debugDescription : "Expected to decode String but found an array instead."
I had this error couple of times but I always managed to find the solution.
I suppose you were using the List conditional conformance to Decodable from my answer to your previous question. I don't fully understand why it doesn't work in this specific case, but I'll investigate.
Until then, you can make decoding work by manually implementing the init(from decoder:Decoder) function.
class User : Object, Decodable {
let items = List<Equipment>()
private enum CodingKeys: String, CodingKey {
case items
}
required convenience init(from decoder:Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
let itemsArray = try container.decode([Equipment].self, forKey: .items)
self.items.append(objectsIn: itemsArray)
}
}

Json results to a string array in swift

Hello i've been trying to make a json request and some of its results i want to put it to an array of string.
So i have the following code
var arrRes = [[String:AnyObject]]()
var nameaRR = [String]()
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(.GET, "https://graph.facebook.com/search", parameters: ["q": "", "type": "place", "center": "37.928319,23.7036673", "distance": "10000","limit": "1000", "access_token": "SomeToken", "expires_in": "5184000"])
.responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let swiftyJsonVar = JSON(responseData.result.value!)
//print(swiftyJsonVar)
if let resData = swiftyJsonVar["data"].arrayObject {
self.arrRes = resData as! [[String:AnyObject]]
self.nameaRR = swiftyJsonVar["data"]["name"] as! [String]
print(self.nameaRR)
}
if self.arrRes.count > 0 {
self.kati.reloadData()
}
}
}
}
The JSON Resul is the following
{
"data" : [
{
"category_list" : [
{
"id" : "272705352802676",
"name" : "Outdoors"
},
{
"id" : "115725465228008",
"name" : "Region"
}
],
"id" : "552889064768971",
"name" : "Παλαιο Φαληρο", //This String i want to put in an Array
"category" : "Local business",
"location" : {
"street" : "",
"city" : "Palaión Fáliron",
"country" : "Greece",
"longitude" : 23.6944070162,
"zip" : "17562",
"latitude" : 37.9284637008,
"state" : ""
}
}
]
}
I get a warning
Cast from 'JSON' to unrelated type '[String]' always fails
But i'm stuck of how can i put all the Strngs to the array nameaRR.
Can anyone help me find my mistake? Thanks!
look do like that
if let resData = swiftyJsonVar["data"] as? [[String:AnyObject]] {
if let categorylist = resData["category_list"] as? [[String:AnyObject]]{
if let id = categorylist["id"] as? Int{
print(id)
}
}
}

Mongodb query for 2 level grouping

Suppose I have documents that, among others, have these fields:
{
"class" : String,
"type" : String,
"name" : String,
}
For example, many like this:
{
"class": "class A",
"type": "type 1",
"Name": "ObjectA1"
}
{
"class": "class A",
"type": "type 2",
"Name": "ObjectA2_1"
}
{
"class": "class A",
"type": "type 2",
"Name": "ObjectA2_2"
}
{
"class": "class B ",
"type": "type 3",
"Name": "ObjectB3"
}
What I want is a query that returns me the following structure
{
"class A" : {
"type 1" : ["ObjectA1"],
"type 2" : ["ObjectA2_1", "ObjectA2_2"]
},
"class B" : {
"type 3" : ["ObjectB3"]
}
}
I tried using aggregate with $group but could not do this. Any thoughts?
PS: I would like to do this on mongodb shell, not mongoose or something like this.
The problem with using the aggregation framework will be that you cannot specify an arbitrary key name for a property of an object. So reshaping using that would not be possible without being able to specify all of the possible key names.
So to get the result you would need to work something in JavaScript such as mapReduce:
First define a mapper:
var mapper = function () {
var key = this["class"];
delete this._id;
delete this["class"];
emit( key, this );
};
Then a reducer:
var reducer = function (key, values) {
var reducedObj = {};
values.forEach(function(value) {
if ( !reducedObj.hasOwnProperty(value.type) )
reducedObj[value.type] = [];
reducedObj[value.type].push( value.Name );
});
return reducedObj;
};
And because you have ( in your sample at least ) possible items that will be emitted from the mapper with only 1 key value you will also need a finalize function:
var finalize = function (key,value) {
if ( value.hasOwnProperty("name") ) {
value[value.type] = value.name;
delete value.type;
delete value.name;
}
return value;
};
Then you call the mapReduce function as follows:
db.collection.mapReduce(
mapper,
reducer,
{ "out": { "inline": 1 }, "finalize": finalize }
)
And that gives the following output:
"results" : [
{
"_id" : "class A",
"value" : {
"type 1" : [
"ObjectA1"
],
"type 2" : [
"ObjectA2_1",
"ObjectA2_2"
]
}
},
{
"_id" : "class B ",
"value" : {
"type" : "type 3",
"Name" : "ObjectB3"
}
}
],
While the result is formatted in a very mapReduce way, it is definitely much the same as your result.
But if you really did want to take that further, you can always do the following:
Define another mapper:
var mapper2 = function () {
emit( null, this );
};
And another reducer:
var reducer2 = function (key,values) {
reducedObj = {};
values.forEach(function(value) {
reducedObj[value._id] = value.value;
});
return reducedObj;
};
Then run the first mapReduce with the output to a new collection:
db.collection.mapReduce(
mapper,
reducer,
{ "out": { "replace": "newcollection" }, "finalize": finalize }
)
Followed by a second mapReduce on the new collection:
db.newcollection.mapReduce(
mapper2,
reducer2,
{ "out": { "inline": 1 } }
)
And there is your result:
"results" : [
{
"_id" : null,
"value" : {
"class A" : {
"type 1" : [
"ObjectA1"
],
"type 2" : [
"ObjectA2_1",
"ObjectA2_2"
]
},
"class B " : {
"type" : "type 3",
"Name" : "ObjectB3"
}
}
}
],
I found a workaround for what I needed. It's not the same but solves my problem.
db.myDb.aggregate(
{
$group:{
_id: {
class_name : "$class",
type_name : "$name"
},
items: {
$addToSet : "$name"
}
}
},
{
$group:{
_id : "$_id.class_name",
types : {
$addToSet : {
type : "$_id.type_name",
items : "$items"
}
}
}
})
this gave me something like:
{
_id : "class A",
types: [
{
type: "type 1",
items: ["ObjectA1"]
},
{
type: "type 2",
items: ["ObjectA2_1", "ObjectA2_2"]
}
]
},
{
_id : "class B",
types: [
{
type: "type 3",
items: ["ObjectB3"]
}
]
}
Both code and example were written here so there may be typos.
So this is about it. I want to thank #Neil Lunn for his awesome answer and dedication.
Marcel