I have a JSON object of this type, very pratical do loop (for each key => value)
It's like JSON of JSON
But I'm not able to decode it in Swift.
I'm trying to know if this type of data is decodable in Swift.
If it would be easy for you, could you please help to decode it? In an array for example.
{"1":{"1":"some text"},"2":{"1":"some text","2":"some text","3":"some text","4":"some text"},"3":{"1":" some text","2":"some text","3":"some text"},"4":{"1":"some text","2":"some text"},"5":{"1":"some text"},"6":{"1":"some text","2":"some text","3":"some text"}}
let jsonDict = json_text
let jsonDictData = jsonDict.data(using: .utf8)!
let object = try? JSONSerialization.jsonObject(
with: jsonDictData,
options: []
)
// Cast to a Swift Dictionary
let dict = object as? [AnyHashable:Any]
// Cast to an NSDictionary
let nsDict = object as? NSDictionary
print(nsDict)
it returns nil
Finally, I parse it by myself.
With .components(separatedBy: "},")
and .components(separatedBy: "\",\"")
and sweeping some characters with .replacingOccurrences(of: pattern, with: "")
pattern id for example pattern = "\"1\":\""
Related
I'm receiving a valid Json string from my HTTP request which looks like this
"[{
"id”:10,
"user_id":"77da74e6-3e03-403d-9c1a-91f231233515”,
"friend_user_id":"fc879bf5-c53d-4a4e-b3a4-dab7a8266a2r”,
"name":"Tommie Smith”,
"type":"active”,
"created_at":"2018-05-02 14:53:09",
"updated_at":"2018-05-02 14:53:09",
"friend_user":{
"id":"fc879bf5-c53d-4a4e-b3a4-dab7a8266a2r",
"first_name”:”Allen”,
"last_name”:”Williams”,
"email”:”allen.williams#example.org",
"date_of_birth":"1996-03-05 00:00:00",
"created_at":"2018-05-02 14:53:07",
"updated_at":"2018-05-02 14:53:07",
"deleted_at":null
}
},
{
"id”:11,
"user_id":"77da74e6-3e03-403d-9c1a-91f231233515”,
"friend_user_id":"96990d13-372e-46f7-9187-94988954455b”,
"name":"Mr. Thomas Atkins”,
"type":"not",
"created_at":"2018-05-02 14:53:10",
"updated_at":"2018-05-02 14:53:10",
"friend_user":{
"id":"96990d13-372e-46f7-9187-94988954455b",
"first_name”:”Trevor”,
"last_name”:”Wright”,
"email”:”trevor.wright#example.net",
"date_of_birth":"1983-07-27 00:00:00",
"created_at":"2018-05-02 14:53:08",
"updated_at":"2018-05-02 14:53:08",
"deleted_at":null
}
}]"
I know that this is what I'm receiving as I'm using the following code to return a string with my data
let string = String(data: data, encoding: String.Encoding.utf8)
However, when I use the code below to parse my data, json returns nil
let json = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject]
What is wrong with this statement?
Please (learn to) read the JSON, it's pretty easy. There are only 2 (two!) different collection types:
{} is dictionary, in Swift [String: Any].
[] is array, in Swift [Any] but in most cases an array of dictionaries [[String: Any]].
so the JSON is clearly an array. In Swift 3+ a JSON value is never AnyObject
let json = try JSONSerialization.jsonObject(with: data) as? [[String: Any]]
Note:
The mistaken double quotes are not the error reason, otherwise jsonObject(with would throw an error
I'm trying to serialize json object like this
let jsonObject: [String: Any] = [
"Description":problemDescription.text!,
"Photo": byteArray
]
let jsonData = try! NSJSONSerialization.dataWithJSONObject(jsonObject, options: .PrettyPrinted)
but I'm getting this type of error:
swift 2 argument type string any does not conform to expected type any object.
Any ideas?
update: It seems that when I'm printing json object after this line
let jsonData = try! NSJSONSerialization.dataWithJSONObject(jsonObject, options: .PrettyPrinted)
that that conversion to byte[] occurs itself. At least seems that way in console debug.
I would like to handle a JSON string that is returned as data from a HTTP call made using Alamofire.
This question uses SwiftyJSON.
However I wanted to go a little bit "lower level" and understand how to convert the response object into a dictionary.
Reasoning is that it feels that a dictionary may be a simple / easy way to access to the JSON values in the response (rather than having to go through the process of converting the response to a JSON object).
This is under the assumption that JSON objects and dictionaries are the same thing (are they?).
Here is the sample function that I wrote:
func question() -> Void{
let response : DataRequest = Alamofire.request("http://aapiurl", parameters: nil)
// Working with JSON Apple developer guide:
// https://developer.apple.com/swift/blog/?id=37
response.responseJSON { response in
if let JSON = response.result.value
{
print("JSON: \(JSON)") // Works!
let data = JSON as! NSMutableDictionary
// Casting fails
// Could not cast value of type '__NSCFArray' (0x19f952150) to 'NSMutableDictionary' (0x19f9523f8).
print("Data: \(data)")
}
}
}
EDIT:
The JSON object seems to be of type Any and does not have any of the methods that are suggested in the answers below.
I have tried to convert it to a Dictionary and got the error below:
A JSON object IS a Dictionary (or possibly an Array at top level).
Note that you should not be using NSMutableDictionary or NSDictionary (or NSArray or NSMutableArray) in Swift.
Also, JSON objects are not working objects. JSON is a way to move data around. It is not to be used as a data source.
If you want to edit the information you get from JSON then you should construct proper data objects from that JSON and work with them.
If you then need to send JSON from this new data then you take your data objects and convert them back to dictionaries and arrays (i.e. JSON objects) and send that data.
Alamofire has the result value of type Any because it usually would be an array or a dictionary. In Swift you normally shouldn't use NS* classes, but rather native swift types such as Array and Dictionary.
You can (should) use optionals to look into the returned JSON object:
if let array = response.result.value as? [Any] {
print("Got an array with \(array.count) objects")
}
else if let dictionary = response.result.value as? [AnyHashable: Any] {
print("Got a dictionary: \(dictionary)")
}
...
Depending on what you expect from your backend, you can treat each of the cases as a success or a failure.
Alamofire.request(myUrl)
.responseJSON {
response in
if let dict = response.result.value as? [String : Any] {
debugPrint(dict)
wishLists.removeAll() //[[String:Any]]
let lists = dict["wishlists"] as! [String: Any]
debugPrint(lists)
for (key, value) in lists {
var list = value as! [String: Any]
wishLists.append(list)
}
debugPrint(wishLists)
self.tableView.reloadData()
}
}
I'm new to Swift - trying to read a JSON file from a URL. My attempt below.
The JSON looks valid - I tested it with JSONLint but it keeps crashing.
Thoughts?
func getRemoteJsonFile() -> NSDictionary {
//Create a new url
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
//check if its nil
if let actualRemoteUrl = remoteUrl {
//try to get the data
let filedata:NSData? = NSData(contentsOfURL: actualRemoteUrl)
//check if its nil
if let actualFileData = filedata {
//parse out the dictionaries
let jsonDict = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.AllowFragments, error: nil) as NSDictionary
return jsonDict
}
}
return NSDictionary()
}
This took me a second to figure out, so I don't blame you for missing it.
The JSON you linked to is minified, so it's difficult to see the structure. Let's take a look at (a fragment of) it after piping it through a prettifier:
[
{
"PlayerId":2501863,
"PlayerName":"Peyton Manning",
"PlayerTeam":"DEN",
"PlayerPosition":"QB",
"PlayerPassingYards":4727,
"PlayerPassingTDs":39,
"PlayerInterceptions":15,
"PlayerRushingYards":-24,
"PlayerRushingTDs":0,
"PlayerReceivingYards":0,
"PlayerReceivingTDs":0,
"PlayerReturnYards":0,
"PlayerReturnTDs":0,
"PlayerFumbleTDs":0,
"PlayerTwoPointConversions":2,
"PlayerFumblesLost":2,
"PlayerTeamLogo":"http://i.nflcdn.com/static/site/7.0/img/logos/teams-gloss-81x54/den.png"
}
]
Huh. It's encased in brackets, which means that it's an array.
It's an array, so you can't cast it as an NSDictionary. Instead, you could cast it as an NSArray, but why not use native Swift types?
Well, if you don't like types, you're about to find out, but I still think that this is a better way, because it forces you to think about the data you're parsing.
So we have the first part of our type definition for this function; it's an array ([]). What components is our array made up of? We could go with a simple NSDictionary, but we're doing full native types here, so let's use a native Swift dictionary.
To do that, we have to know the types of the dictionary (the syntax for a native dictionary type is [KeyType: ValueType]). Examining the JSON shows that all of the keys are Strings, but the values are of varying types, so we can use AnyObject.
That gives us a dictionary type of [String: AnyObject], and our entire JSON is an array of that, so the final type is [[String: AnyObject]] (wow).
Now that we have the proper type, we can modify the function you're using to parse the JSON a bit.
First of all, let's use our new type for the return and cast values. Then, let's make the return type optional in case something goes wrong and add an error variable to document that.
A cleaned up function would look something like this:
func getData() -> [[String: AnyObject]]? {
let data: NSData? = NSData(contentsOfURL: NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")!)
if let req: NSData = data {
var error: NSError?
if let JSON: [[String: AnyObject]] = NSJSONSerialization.JSONObjectWithData(req, options: NSJSONReadingOptions.AllowFragments, error: &error) as? [[String: AnyObject]] {
return JSON
}
}
return nil
}
That's it!
We can now call the function and extract values from our [[String: AnyObject]] (again, wow) like this:
if let data: [[String: AnyObject]] = getData() {
println(data[0]["PlayerName"]!) // Peyton Manning
}
Update your code with this:
func getRemoteJsonFile() -> [NSDictionary] {
// Create a new URL
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
let urlString:String = "\(remoteUrl)"
// Check if it's nil
if let actualRemoteUrl = remoteUrl {
// Try to get the data
let fileData:NSData? = NSData(contentsOfURL: actualRemoteUrl)
// Check if it's nil
if let actualFileData = fileData {
// Parse out the dictionaries
let arrayOfDictionaries:[NSDictionary]? = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.MutableContainers, error: nil) as [NSDictionary]?
if let actualArrayOfDictionaries = arrayOfDictionaries {
// Successfully parsed out array of dictionaries
return actualArrayOfDictionaries
}
}
}
return [NSDictionary]()
}
This is working fine for me.
For backend communication, my app requires a method to create a certainly structured JSON, and thats where i struggle.
The created JSON is supposed to look like this:
{
"data": {
"color":"yellow",
"size":"big"
}
}
Serializing a Dictionary with the required Data does not really seem to have the option to format the content properly, my best results look like this:
Optional({
Kategorie = Strassenschaeden;
PLZ = 46282;
Strasse = Erftweg;
Unterkategorie = Schlagloch;
})
I didnt find any helpful weblinks for my problem, and since im new to Swift and its documentation Im kinda stuck at the moment.
So my questions are:
Whats the preferred data structure for my JSON data (Dictionary/Array) and how do I create a JSON that is well-formated?
Thanks in advance :)
Edit: This is the interesting part of what i have used to achieve my "best result":
var data: [String: String] = ["Kategorie": "\(Kategorie)", "Unterkategorie": "\(Unterkategorie)", "Strasse": "\(Strasse)","PLZ": "\(PLZ)"]
self.post(data, url: "http://*************") { (succeeded: Bool, msg: String) -> () in
var alert = UIAlertView(title: "Success!", message: msg, delegate: nil, cancelButtonTitle: "Okay.")
func post(params : Dictionary<String, String>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
let JSONData:NSData = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted, error: &err)!
var json = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &err) as? NSDictionary
println(json)
Here
let JSONData:NSData = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted, error: &err)!
var json = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &err) as? NSDictionary
you are converting the params dictionary to JSON data – and then you convert the
JSON data back do a dictionary! What you probably want is to create a string
from the JSON data:
let jsonData = NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted, error: &err)!
let json = NSString(data: jsonData, encoding: NSUTF8StringEncoding)!
println(json)
Remarks:
Properties and variables should have names starting with lower case letters, e.g.
jsonData.
The explicit type annotation :NSData is not needed here, the Swift compiler can
infer the type automatically.
The option can be given as .PrettyPrinted instead of NSJSONWritingOptions.PrettyPrinted, the compiler infers the enumeration type
automatically.
Instead of forced unwrapping with ! you should use optional binding to check
for success.
Just an itch, that no one here recommend swiftyJSON for working with JSON in Swift.
Try it, you will lose your pain of dealing with JSON.
https://github.com/SwiftyJSON/SwiftyJSON
To Read JSON
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let jsonObject = JSON(data: jsonData!)
To Write JSON
let jsonString = jsonObject.rawString()