Parsing array literal from JSON in Swift 3 - arrays

I have a PHP script that returns a JSON response in the format of an array literal.
Example of exactly what it returns:
["school","chess_club"]
However, I am unable to parse it in Swift after I received the response successfully.
Code:
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
print (json)
Error:
Could not cast value of type '__NSArrayI' (0x10a440d88) to 'NSDictionary' (0x10a441288).
Note on duplicate:
I found this duplicate, Could not cast value of type '__NSArrayI' (0x10df73c08) to 'NSDictionary' (0x10df74108), but I can't figure out how can I use it to fix the error in my situation.
Specifically, I don't get how am I casting it to a NSDictionary since I didn't specify anywhere in my code "NSDictionary".

[String:AnyObject] is a Dictionary Object although you didn't specify it. Try this:
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String]
print (json)

Related

How do could you get specific blocks of data from a JSON array Swiftui

I haven't written any code yet but I have a JSON which I want to get a specific block of data from to display on a very rudimentary view. I just want to grad a block of data that is nested in a JSON. Is there method for doing such a thing simply with swiftui? Im a beginner at Swiftui.
Decoding/getting the data
There are multiple ways to access specific blocks of data from JSON data.
If you fetch your JSON object from an API, you'll likely need to decode it (Data type to custom type).
First method: using SwiftyJSON
There is a great library to access specific parts of a JSON object which is called SwiftyJSON.
They provide a few examples like this one:
let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
//Now you got your value
}
Second method: using pure Swift
You have to serialize your JSON object and afterwards, you can access a specific block using:
if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
let user = statusesArray[0]["user"] as? [String: Any],
let username = user["name"] as? String {
// Finally we got the username
}
Third method: using custom Structs and Enums
The last method is to create a data model and parse your JSON. To create your data model you can use an app called quicktype.
You can then decode simply. Here's a link to show you how.
Using/displaying the data
After decoding the data, you can parse it to an ObservableObject and loop through it using a List or a ForEach.

Working with Unsplash. Cannot assign value of type 'Array<_>' to type 'Any?'

Currently, I'm working on processing information I've received from a JSON file, and as it's organized into multiple levels, I need to be able to convert not only the file, but all of its contents into the correct file types. I'm having some issues with this, and I can't find anything for Swift on this issue.
So far, I've tried the methods that are apparent within the code below. I couldn't find much information on alternate methods to do this, and I'm still new to programming, so I haven't been able to do much.
URLSession.shared.dataTask(with: urlRequest) { data, response, error in
if let data = data {
print("Clear")
let returnData = String(data: data, encoding: .utf8)
do {
let image = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
print(image!["results"])
var imgl2 = image!["results"]
imgl2 = imgl2 as! Array
//imgl2 = imgl2![0]
//print(imgl2!["color"])
// var imgl3 = imgl2!["results"]
// var imgl4 = imgl3!["results"]
// var imgl5 = imgl4!["results"]
// var imgl6 = imgl5!["results"]
} catch let error {
print(error)
}
}
}.resume()
What should happen here is that I should be able to convert the JSON's contents into the correct file types. To some extent, this works, and I'm able to obtain the first level of results. However, partway through the process at imgl2 = imgl2 as! Array, I can't convert it to an Array. Instead, I receive the error (Cannot assign value of type 'Array<_>' to type 'Any?'). I'd really like to be able to use the array enclosed, but I can't. After this, there will be several additional levels of content that I will need to sort through in this manner. I've tried looking at the API documentation, but I don't understand the way they've written it (this is Unsplash, by the way), and as such, I've tried this method. How exactly would I go about this?
(For further information, I'm trying to pull out the first image in the results, so that I can then edit it programmatically. I need the URL enclosed in the response to the search query, but the way the documentation is worded is unclear enough, and solutions to this problem so sparse, that I've had to use trial and error to get to where I am. Any insight into how to accomplish this would be greatly appreciated.)
Cannot assign value of type 'Array<_>' to type 'Any?
The error tells you that imgl2 is of type Any?, but you're trying to assign it a value of type Array. Swift doesn't allow changing the type of a variable after it has been initialized. What you could do is to assign imgl2 as! Array to a new variable to avoid this error.
I also suggest you to have a look at Decodable protocol to create models corresponding to the JSON structure.

Store a NSMutableArray of NSManagedObject arrays in core data | swift 2

I'm somewhat new to swift, and I'm not a master when it comes to arrays
I'm trying to find a way where I can store an array of NSManagedObjects into core data.
Here's an example:
let array = [["a", "b", "c",],["1", "2", "3",],["apple", "orange", "pear"]]
This is the way I did it:
I have several arrays of NSManagedObjects that I added to a NSMutableArray
Then I stored it as transformable data. Like this.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity_entry = NSEntityDescription.entityForName("EntityForArrays", inManagedObjectContext: managedContext)
let new_value = NSManagedObject(entity: entity_entry!, insertIntoManagedObjectContext: managedContext)
new_value.setValue(array, forKey: "attribute")
So am I going down the right path by using a NSMutableArray or should I try something new?
Also if can store this array, how can I receive it?
Whether it's the right path depends on how you need to use that array. It's convenient to put it all into one transformable attribute, but you can't use predicates to fetch objects based on their array contents.
Saving the array like that should work. To get it back, fetch objects using NSFetchRequest and then look up the array value using valueForKey().

Encoding toJSON from Arrays and Dictionaries in Swift

I am trying to create a JSON file from an array that i make inside my application with swift.
I need to encode to JSON an 'Array' because i am creating dictionaries and arrays before and i just combine them to that array.
In my code i have :
var order = Array<Any>()
var orderArray = Array<Dictionary<String, String>>()
var dict = Dictionary<String, Any>()
and i put first the orderArray in dict and then the dict inside order.
The output if i print it is correct and it works. The problem is when i try to encode the order(array) into JSON. Then i get the following error:
Cannot invoke 'dataWithJSONObject' with an argument list of type '(Array'
This is the code i use:
let json = NSJSONSerialization.dataWithJSONObject(order, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
If i try the same code with the orderArray for example it works.
The 'Any' i think does the mess. But how could i resolve this?
Thank you.

Parse.com Query with swift 1.2 and string array

I am trying to query from parse.com and I would db receiving about 100 objects per time. I used the swift example code on their website, and the app doesn't build with that code. So I looked around and found that people were using code similar to this:
var query = PFQuery(className:"posts")
query.whereKey("post", equalTo: "true")
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
// do something
self.myDataArray = objects as! [String]
})
This does not work, because I am trying to convert PFObject to String
I would need to get the one one value from each object into a swift string array [String]. How do I get just the one text value, instead of the PFObject and how do I get it into the swift string array?
I don't speak swift very well, but the problem with the code is it's trying to cast the returned PFObject to a string, but you want to extract a string attribute, so (if you really want to do it):
for object in objects {
var someString = object.valueForKey("someAttributeName") as String
self.myDataArray.addObject(someString)
}
But please make sure you need to do this. I've noticed a lot of new parse/swift users (especially those who are populating tables) have the urge to discard the returned PFObjects in favor of just one of their attributes. Consider keeping the PFObjects and extracting the attributes later as you need them. You might find you'll need other attributes, too.
For starters, I would definitely recommend using the "if let" pattern to qualify your incoming data. This is a nice Swift feature that will help avoid run-time errors.
var query = PFQuery(className:"posts")
query.whereKey("post", equalTo: "true")
query.findObjectsInBackgroundWithBlock(
{ (objects: [AnyObject]?, error: NSError?) -> Void in
// check your incoming data and try to cast to array of "posts" objects.
if let foundPosts = objects as? [posts]
{
// iterate over posts and try to extract the attribute you're after
for post in foundPosts
{
// this won't crash if the value is nil
if let foundString = post.objectForKey("keyForStringYouWant") as? String
{
// found a good data value and was able to cast to string, add it to your array!
self.myDataArray.addObject(foundString)
}
}
})

Resources