Swift: Split every item in JSON-Array into single file - json

I have a JSON-NSArray (created with NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)...), containing a few items and want to save every item in it as a single file on my local disk.
I've wrote the following function to save a local json-file:
func writeLocalFileFromString(dataString dataString: String, path: String, filename: String, type: String) {
do {
try dataString.writeToFile("\(path)/\(filename).\(type)", atomically: true, encoding: NSUTF8StringEncoding)
} catch let error {
print(error)
}
}
So I tried to cast every json-item as! String. The files are created and they're containing a good-looking string, but however, they're not valid json-files. Is there a better way to handle this?

You loop and get every item in json NSDictionary, then convert this item json format. Instead of print it as the code block below, you can save it to file as you want.
let json = try! NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers) as! NSDictionary
// loop to get item
for (key, value) in json {
// data is a NSData contains your json string
let data = try! NSJSONSerialization.dataWithJSONObject([key, value], options: [])
// convert NSData to String, then do what you want
let string = String(data: data, encoding: NSUTF8StringEncoding)
print(string)
}

Related

Convert string preceeded with 0 to Json in Swift 4

I'm trying to encode an integer that starts with a 0 into JSON using swift 4.
I'm using a pretty standard JSONSerialization library, but for some reason, after converting the string to data using utf8, I cannot serialize it.
let code = "012345" // example code
let body = "{\"code\": " + code + "}"
let stringData = body.data(using: .utf8)!
let jsonArray = try? JSONSerialization.jsonObject(with: stringData, options : .allowFragments) [returns nil]
let data: Data? = try? JSONSerialization.data(withJSONObject: jsonArray as Any, options: .prettyPrinted)
Currently, the code breaks on the second to last line (starting with let jsonArray) and returns nil. Note that if I were to change code to "112345", there would be no error. Any help is appreciated, thanks!
Instead of manually creating string, use Dictionary and JSONSerialization to create data as below,
let code = "012345"
let body: [String: Any] = ["code": code]
do {
let stringData = try JSONSerialization.data(withJSONObject: body, options: .sortedKeys)
print(String.init(data: stringData, encoding: .utf8)!)
} catch {
print(error)
}
Output
{"code":"012345"}

iOS Swift:"JSON text did not start with array or object and option to allow fragments not set."

When I converting Json string to dictionary in swift I got the Issue:Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
I don't know to fix the issue please give idea for fix the issue.Here I gave my code what i am tried..
The method for converting Json string to dictionary is,
func convertToDictionary(from text: String) throws -> [String: String] {
guard let data = text.data(using: .utf8) else { return [:] }
let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: [])
return anyResult as? [String: String] ?? [:]
}
The Json String is: "[{\"propertyId\":\"1\",\"inspectionTemplateId\":1118,\"value\":[{\"widgetControllerId\":141,\"value\":\"Flood Summary Name\"},{\"widgetControllerId\":142,\"value\":\"Did the property flood?\"},{\"widgetControllerId\":143,\"value\":\"no\"}]}]"
And the Usage of method was:
let jsonString = NSString(data: responseObject as! Data, encoding: String.Encoding.utf8.rawValue)!
print(jsonString)
do {
let dictionary:NSDictionary = try self.convertToDictionary(from: jsonString as String) as NSDictionary
print(dictionary)
} catch {
print(error)
}
Read the error gentleman. Error is 'allow fragments not set'.
Just Just just set .allowFragments.
That's it. (Make sure response is not malformatted)
JSONSerialization.jsonObject(with: data!, options: .allowFragments)
You can try this:
let str = "[{\"propertyId\":\"1\",\"inspectionTemplateId\":1118,\"value\":[{\"widgetControllerId\":141,\"value\":\"Flood Summary Name\"},{\"widgetControllerId\":142,\"value\":\"Did the property flood?\"},{\"widgetControllerId\":143,\"value\":\"no\"}]}]".utf8
let json = try! JSONSerialization.jsonObject(with: Data(str), options: [])
print(json)
This type of issue can also occur if you have a misconfigured server or your server is unreachable. If you receive this type of error from JSON deserialization you may try converting the data to a string and print it out. It may reveal an error like "502 Bad Gateway"

Swift JSONSerialization implicitly convert double value to string

I want convert a json string which contains a double field to JSON object using JSONSerialization.data function. I print the result json object and it shows the double field as string. The following is the sample code:
let test = "{\"statusCode\":2.334}"
do {
let responseJSON = try JSONSerialization.jsonObject(with: test.data(using: String.Encoding.utf16)!, options: [])
print(responseJSON)
} catch {
print(error)
}
The responseJSON as following:
{
statusCode = "2.334";
}
I have two questions:
Is it, in general, all JSON serialization engine will convert double
value to string or it is only happen in Swift JSON serialization?
Anyway to force JSONSerialization to output double, not string?
This is purely an artifact of how the value is printed out — the value you get is in fact a Double. You can confirm this yourself with the following:
import Foundation
let test = "{\"statusCode\":2.334}"
do {
let responseJSON = try JSONSerialization.jsonObject(with: test.data(using: String.Encoding.utf16)!, options: []) as! [String: Any]
print(responseJSON["statusCode"] is Double) // => true
} catch {
print(error)
}

JSON with Swift 2, Array Structure

I'm Having trouble with JSON and Swift 2.
I'm getting this Array from the server
[{"KidName":"Jacob","KidId":1,"GardenID":0},
{"KidName":"Sarah","KidId":2,"GardenID":0},
{"KidName":"Odel","KidId":3,"GardenID":0}]
I'm familiar with JSON and I know it's not the recommended way to get a JSON, since it's supposed to be something like
{"someArray":[{"KidName":"Jacob","KidId":1,"gardenID":0}, .....
So my first question is it possible to run over the first JSON I've post and get the KidName number without editing the JSON and Add to it a JSON OBJECT to hold the array ?
my second question is really with Swift 2, how can I get the KidName (after I've edited the JSON to have an holder for the array)?
this is my code... (please read the Notes I've added)
BTW, I'm familiar with SwiftyJSON as well...
// Method I've build to get the JSON from Server, the Data is the JSON
sendGetRequest { (response, data ) -> Void in
// need to convert data to String So I can add it an holder
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
/**
after editing the str, i'm Having a valid JSON, let's call it fixedJSON
*/
let fixedJSON = "{\"kidsArray\":\(dropLast)}"
// Now I'm converting it to data back again
let jsonTodata = fixedJSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
// After Having the data, I need to convert it to JSON Format
do{
let dataToJson = try NSJSONSerialization.JSONObjectWithData(jsonTodata, options: []) as! [String:AnyObject]
//Here I'm getting the KidID
if let kidID = jsonSe["kidsArray"]![0]["KidId"]!!.integerValue {
print("kidID in first index is: \(kidID)\n")
}
//NOW trying to get the KidName which not working
if let kidname = jsonSe["kidsArray"]![0]["KidName"]!!.stringValue {
print("KidName is \(kidname)\n")
}
}
So as you can see, I'm not able to get the KidName.
Any Help Would be Appreciate.
You can use the following function to get the 'someArray' array and then use this getStringFromJSON function to get the 'KidName' value.
func getArrayFromJSON(data: NSDictionary, key: String) -> NSArray {
if let info = data[key] as? NSArray {
return info
}
else {
return []
}
}
let someArray = self.getArrayFromJSON(YourJSONArray as! NSDictionary, key: "someArray")
func getStringFromJSON(data: NSDictionary, key: String) -> String {
if let info = data[key] as? String {
return info
}
return ""
}
let KidName = self.getStringFromJSON(someArray as! NSDictionary, key: "KidName")
Hope this might be useful to you.

Swift - Reading JSON File

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.