Swift JSONSerialization implicitly convert double value to string - json

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)
}

Related

Swift MacOS getting bad json response from jsonSerialization

I am trying to convert a string to JSON in Swift.
Here's the string, which I am getting by pulling the innerHTML from a WKWebView.
{"list":{"pagination":{"count":3,"hasMoreItems":false,"totalItems":3,"skipCount":0,"maxItems":100},"entries":[{"entry":{"createdAt":"2020-06-16T21:00:32.714+0000","isFolder":false,"isFile":true,"createdByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"modifiedAt":"2020-06-16T21:00:32.714+0000","modifiedByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"naxxxxxxxxme":"00-invest-2020-06-16-17-00-32-716.txt","id":"028b4c82-09b8-4ee5-b4fa-9696a33b026d","nodeType":"log:fileNode","content":{"mimeType":"text/plain","mimeTypeName":"Plain Text","sizeInBytes":609373,"encoding":"UTF-8"},"parentId":"ba647bfc-a889-4d91-9211-4220cfe7d90a"}},{"entry":{"createdAt":"2020-06-16T21:01:12.828+0000","isFolder":false,"isFile":true,"createdByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"modifiedAt":"2020-06-16T21:01:12.828+0000","modifiedByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"name":"00-monetize-2020-06-16-17-01-12-830.txt","id":"d6412e3a-fea5-4d4d-a962-d91cde294bc9","nodeType":"log:fileNode","content":{"mimeType":"text/plain","mimeTypeName":"Plain Text","sizeInBytes":996653,"encoding":"UTF-8"},"parentId":"ba647bfc-a889-4d91-9211-4220cfe7d90a"}},{"entry":{"createdAt":"2020-06-16T18:33:49.344+0000","isFolder":true,"isFile":false,"createdByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"modifiedAt":"2020-06-16T18:34:49.211+0000","modifiedByUser":{"id":"UserFName.userLName#xxxxxxxx.com","displayName":"UserFName userLName"},"name":"20200616","id":"d881db96-ddcb-44ae-99e1-ffe3ac0c2810","nodeType":"cm:folder","parentId":"2fcf4c49-be4c-4f2c-a90b-654ae092c63e"}}]}}
I've checked the string in JSON Lint and it says it is valid.
Here's what I am doing in my code to convert it:
let strJSONLiteral = """
\(strJSON)
"""
//convert string to json
let data = strJSONLiteral.data(using: .utf8)!
do {
if let myJSON = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]
{
print(myJSON) // use the json here
} else {
print("bad json")
}
} catch let error as NSError {
print(error.localizedDescription)
}
The error is occurring in the JSONSerialization attempt. I'm getting nil for myJSON. Data check looked ok, has 1600+ bytes.
The top-level JSON is of type Dictionary while you're trying to decode an Array of Dictionary. To fix this
Replace:
if let myJSON = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]
With:
if let myJSON = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? Dictionary<String,Any>
Or you can just use [String: Any].
Add-on: You should probably do a bit of research on Codable and try to use it for these scenarios.

Swift JSON validation fails this data from my web api, I do not know why

Here is the swift code
if JSONSerialization.isValidJSONObject(JSONData) {
print (":Valid json")
} else {
let JSONstring = NSString(data: JSONData, encoding: String.Encoding.utf8.rawValue)
print(JSONstring)
}
which results in the 'else' part being executed, and outputs the JSON data converted to a string as follows:
Optional("[{\"nPropertyID\":4,\"sAddress_1\":\"11 Some street\",\"sAddress_2\":\"Some Road\",\"sAddress_3\":\"Toytown\",\"sPostcode\":\"AB1 9XX\",\"dPurchaseCost\":9999.99,\"dtPurchaseDate\":\"2012-10-23T00:00:00\"}]")
According to Apple documentation you can't use isValidJSONObject with Data or String objects (even if the input parameter is of type Any):
Returns YES if the given object can be converted to JSON data, NO
otherwise. The object must have the following properties:
Top level object is an NSArray or NSDictionary
All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
All dictionary keys are NSStrings
NSNumbers are not NaN or infinity
Instead you can use:
let jsonStr = "[{\"nPropertyID\":4,\"sAddress_1\":\"11 Welch House\",\"sAddress_2\":\"Beaconsfield Road\",\"sAddress_3\":\"Enfield\",\"sPostcode\":\"EN3 6UX\",\"dPurchaseCost\":88000.00,\"dtPurchaseDate\":\"2012-10-23T00:00:00\"}]"
if let jsonDataToVerify = jsonStr.data(using: .utf8)
{
do {
_ = try JSONSerialization.jsonObject(with: jsonDataToVerify)
print("JSON is valid.")
} catch {
print("Error deserializing JSON: \(error.localizedDescription)")
}
}
As suggested here.

how to convert JSON dictionary to string value in swift 4

I'm new to Swift and I started working on a Swift 4 project with a PHP server.
I use Alamofire for requests, and print the data using print(). This is is what i'm getting:
{"error":false,"n":"Raghad"}
But when I want to convert it to String, it returns "" (empty) and
when I convert to boolean it returns the value correctly.
So, how can I fix it?
let wJSON : JSON = JSON(response.result.value!)
print(wJSON["n"].stringValue)
print(wJSON["error"].boolValue)
Simple solution using Decodable, define a Struct that conforms to the Decodable protocol for your dictionary
struct Reply: Decodable {
let error: Bool
let n: String
}
let data = response.data
do {
let result = try JSONDecoder().decode(Reply.self, from: data)
print("\(result.n) \(result.error)")
} catch {
print(error)
}
I change the responseString to responseJSON
Alamofire.request(Url!, method: .post, parameters: par).validate().responseJSON { response in if response.result.isSuccess { let wJSON : JSON = JSON(response.result.value!)
and it's work

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"

Problems parsing json String to objects in Swift

I googled a lot, pretty much copied code i found online from tutorials to simply parse a json String in Swift to useable objects.
Code:
func parseJson(json: String) -> [AnyObject] {
let data = json.dataUsingEncoding(NSUTF8StringEncoding)
do {
if let array = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? [AnyObject] {
return array
}
}
catch {
// Error hanndling here
}
return [AnyObject]()
}
Json String im trying to parse:
"response":{"loggedIn":false,"message":"Some errormessage here"}}
What happens:
The program won't jump into the if let array = ... It stops there since it can't parse the string to json (or AnyObject) and will simply go to return AnyObject.
Why does this happen and how do i fix it?
Adjust your code a little to allow for better debugging:
func parseJson(json: String) -> [AnyObject] {
let data = json.dataUsingEncoding(NSUTF8StringEncoding)
do {
let parsed = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
if let array = parsed as? [AnyObject] {
return array
}
}
catch {
print(error)
}
return [AnyObject]()
}
Two changes there:
Printing any error caught.
Doing JSONObjectWithData and the as? conversion in two separate steps.
Pasting this in a playground quickly reveals an error being caught: "JSON text did not start with array or object and option to allow fragments not set." Your JSON fragment is missing the opening {.
Once that problem is fixed, you’ll see that parsed gets set, but the subsequent if let array = parsed as? [AnyObject] falls through. That’s because your top-level element is a dictionary, not an array, so casting to [AnyObject] fails.