Swift 4 parse string to json object - ios

I have implement qr code scanner, Where in "metadataOutput" delegate method I have received response which has key like "stringValue", Value of this key is
stringValue "'{ "part_number":"154100102232",
"lot_number":"03S32401701344"}'"
I want parse string value to json object, but I am not able to do that.
let data = stringValue.data(using: .utf8)!
do {
if let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [AnyHashable:Any]
{
print("Json:::",json)
// post a notification
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SCANNER_DATA"), object: nil, userInfo: json)
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
I have followed above approach to parse string to json, but I have found following error.
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around
character 0." UserInfo={NSDebugDescription=Invalid value around
character 0.}
Can anyone have any idea about this?

Better have an extension to String like this
extension String{
func toDictionary() -> NSDictionary {
let blankDict : NSDictionary = [:]
if let data = self.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
} catch {
print(error.localizedDescription)
}
}
return blankDict
}
}
Use like this
let dict = stringValue.toDcitionary()
Or you can use pod for all these kind of work from UtilityKit on github https://github.com/utills/UtilityKit

This works with me , You string has ' character around trailing "' content '"
let stringValue = """
{"part_number":"154100102232","lot_number":"03S32401701344"}
"""
let data = stringValue.data(using: .utf8)!
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String:Any]
{
print("ewtyewytyetwytewytewtewytew",json)
} else {
print("ewtyewytyetwytewytewtewytew","bad json")
}
} catch let error as NSError {
print("ewtyewytyetwytewytewtewytew",error)
}

Related

Error Domain=NSCocoaErrorDomain Code=3840 When JsonString parsing in Swift5

I'm getting a push message. It seems to be jsonString.
But this is not changed into jsonArray. What's the problem?
AppDelegate.swift
guard
let aps = data[AnyHashable("aps")] as? NSDictionary,
let alert = aps["alert"] as? NSDictionary,
let body = alert["body"] as? String
else {
Log.Error("it's not good data")
return
}
let jsonStringData : Data = body.data(using: .utf8)!
Log.Info(jsonStringData)
do {
let jsonArray = try JSONSerialization.jsonObject(with: jsonStringData, options : .allowFragments) as? [Dictionary<String,Any>]
Log.Info(jsonArray) // use the json here
} catch let error as NSError {
Log.Error(error)
}
Value of body (String)
{
notification : {
"title" : "test title.",
"body" : "test context."
},
data : {
"image" : "http://11.111.111.111:100000000/_img/sample_01.jpg",
"page_url" : "http://11.111.111.111:100000000/test?address=",
"type" : "test"
}
}
The log of body is like this in JSON form. But this is not translated. I don't know what I'm missing.
**Error is : **
Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in
object around character 7." UserInfo={NSDebugDescription=No string key
for value in object around character 7.}
Thank you for #vadian and #Larme and #Sh_Khan and #Kamran
As you said, JSON was not valid. This should have been received by JSON. And as #Larme said, I didn't need options, I didn't need to set as. It rather showed me a warning.
It's worked
guard
let aps = data[AnyHashable("aps")] as? NSDictionary,
let alert = aps["alert"] as? NSDictionary,
let body = alert["body"] as? String
else {
Log.Error("it's not good data")
return
}
let jsonStringData : Data = body.data(using: .utf8)!
Log.Info(jsonStringData)
do {
let json = try JSONSerialization.jsonObject(with: jsonStringData, options: [])
Log.Info(json) // use the json here
guard let jsonArray = json as? [String: Any] else {
return
}
Log.Debug(jsonArray)
Log.Debug(jsonArray["data"])
} catch let error as NSError {
Log.Error(error)
}

Converting JSON array string to JSON array returns null

I use alamofire for requests. Here on a simple response, I'm getting this JSON string from alamofire
Optional("[{\"nl2br\":\"2019-05-02 19:52:10\",\"nl3br\":\"\",\"nl4br\":\"#lxr\",\"nl5br\":\"1\",\"nl6br\":\"nein\",\"nl7br\":\"bARxrdw9c7WS1RN9c\\/\\/MrA==822b5dd20cb73611:35cab43d0c7e82e73c62818d9f90cfe8\",\"nl8br\":\"tBDSzkQ7eCNERwldgZiwKg==a7590d9d8affdbe5:63b9a9bf6421ea7db2a55f8773990b08\",\"nl9br\":\"fpd17pxVUzcJWNskVWyBeA==cf21783de8334248:a93e8b8a92ef9b238b75ad87a315ce3e\"},{\"nl2br\":\"2019-04-26 21:36:32\",\"nl3br\":\"old\",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"ja\",\"nl7br\":\"emjUIzK92fWwHNLv\\/4xv2Q==8fca202c9a816c7b:655ef8aaaa0212bb9e77a9c35a56c3a7\",\"nl8br\":\"1C5Hy\\/ZhMk3b6SZY8c08lw==cb3b0f4fdd6b5957:034e72d400598fedc43b3111d841a31b\",\"nl9br\":\"KUfLHbih9612dhNCYPOrTg==48da9c3362430e01:3a80ba9fb516e4172aa39b017abcd96e\"},{\"nl2br\":\"2019-04-26 21:20:24\",\"nl3br\":\"holder\",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"ja\",\"nl7br\":\"J59nMBWUMyU9PzdbwQqd0g==f7d3c6c561c33f0b:3465e9131a2577c39cddcc606d0785b0\",\"nl8br\":\"G4rRevk951ZBJJQKzBeJZg==45c0ebcdc1e000e8:dc770c3849fef8b058f85cad42c73e1d\",\"nl9br\":\"338Ud9CIDgnyBV96F2Fx\\/w==d0f825064e0ecf81:0ca00ff27e977ef5f8123d38c643a8b3\"},{\"nl2br\":\"2019-04-10 23:57:17\",\"nl3br\":\"\",\"nl4br\":\"Wasmes, here\'s a video and do ya need?\",\"nl5br\":\"1\",\"nl6br\":\"ja\",\"nl7br\":\"fw17O1L9SuO9FS3qu6U7QQ==706bd09ee3b5ec55:6667d9020a0edcacbd217f631d2305c0\",\"nl8br\":\"2tTE9+0Kr6cVSuEOsq8h0w==3e0e46352da323be:941710bd881546dfa08d3afb6aea2831\",\"nl9br\":\"NAkMx0OsKwXVGndYXbAFmA==1234c0b2992502bf:666f8efd3bdf8ee8b0a2ee4e7222c2ef\"},{\"nl2br\":\"2019-02-22 21:38:16\",\"nl3br\":\"i\'m giving up on you, but don\'t \",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"nein\",\"nl7br\":\"gOv13Dsxf1N2UG46KT3tvQ==dd02a83b1837bb24:4f7c7ab95e873d35685ab7b738626f44\",\"nl8br\":\"40+GOpcNU6M4F688DJyxFA==70bc177842f3f6cf:232b065423bd2683d75ca177775fd352\",\"nl9br\":\"mBc3pEHKBiiPeAEpZRskug==71b353fed6403b99:c58099676beacc146c14867645e29783\"}]")
I get my data like this and convert it like this
if let responseData = response.data {
let responseDataString = String(data: responseData, encoding:String.Encoding(rawValue: String.Encoding.utf8.rawValue))
print(responseDataString) // gives the whole string above
if let obj = responseDataString?.toJSON() as? [String:AnyObject] {
print(obj["nl2br"] as! String) // gives nothing, just nil
}
}
My string extension is like this.
extension String {
func toJSON() -> Any? {
guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
}
}
Any idea why this behaviour is expected? I tried printing obj that gives nothing too.
Your root is an array not a dictionary Change responseDataString?.toJSON() as? [[String:Any]]
extension String {
func toJSON() -> Any? {
return try? JSONSerialization.jsonObject(with: Data(self.utf8))
}
}
let responseDataString:String? = """[{\"nl2br\":\"2019-05-02 19:52:10\",\"nl3br\":\"\",\"nl4br\":\"#lxr\",\"nl5br\":\"1\",\"nl6br\":\"nein\",\"nl7br\":\"bARxrdw9c7WS1RN9c\\/\\/MrA==822b5dd20cb73611:35cab43d0c7e82e73c62818d9f90cfe8\",\"nl8br\":\"tBDSzkQ7eCNERwldgZiwKg==a7590d9d8affdbe5:63b9a9bf6421ea7db2a55f8773990b08\",\"nl9br\":\"fpd17pxVUzcJWNskVWyBeA==cf21783de8334248:a93e8b8a92ef9b238b75ad87a315ce3e\"},{\"nl2br\":\"2019-04-26 21:36:32\",\"nl3br\":\"old\",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"ja\",\"nl7br\":\"emjUIzK92fWwHNLv\\/4xv2Q==8fca202c9a816c7b:655ef8aaaa0212bb9e77a9c35a56c3a7\",\"nl8br\":\"1C5Hy\\/ZhMk3b6SZY8c08lw==cb3b0f4fdd6b5957:034e72d400598fedc43b3111d841a31b\",\"nl9br\":\"KUfLHbih9612dhNCYPOrTg==48da9c3362430e01:3a80ba9fb516e4172aa39b017abcd96e\"},{\"nl2br\":\"2019-04-26 21:20:24\",\"nl3br\":\"holder\",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"ja\",\"nl7br\":\"J59nMBWUMyU9PzdbwQqd0g==f7d3c6c561c33f0b:3465e9131a2577c39cddcc606d0785b0\",\"nl8br\":\"G4rRevk951ZBJJQKzBeJZg==45c0ebcdc1e000e8:dc770c3849fef8b058f85cad42c73e1d\",\"nl9br\":\"338Ud9CIDgnyBV96F2Fx\\/w==d0f825064e0ecf81:0ca00ff27e977ef5f8123d38c643a8b3\"},{\"nl2br\":\"2019-04-10 23:57:17\",\"nl3br\":\"\",\"nl4br\":\"Wasmes, here\'s a video and do ya need?\",\"nl5br\":\"1\",\"nl6br\":\"ja\",\"nl7br\":\"fw17O1L9SuO9FS3qu6U7QQ==706bd09ee3b5ec55:6667d9020a0edcacbd217f631d2305c0\",\"nl8br\":\"2tTE9+0Kr6cVSuEOsq8h0w==3e0e46352da323be:941710bd881546dfa08d3afb6aea2831\",\"nl9br\":\"NAkMx0OsKwXVGndYXbAFmA==1234c0b2992502bf:666f8efd3bdf8ee8b0a2ee4e7222c2ef\"},{\"nl2br\":\"2019-02-22 21:38:16\",\"nl3br\":\"i\'m giving up on you, but don\'t \",\"nl4br\":\"\",\"nl5br\":null,\"nl6br\":\"nein\",\"nl7br\":\"gOv13Dsxf1N2UG46KT3tvQ==dd02a83b1837bb24:4f7c7ab95e873d35685ab7b738626f44\",\"nl8br\":\"40+GOpcNU6M4F688DJyxFA==70bc177842f3f6cf:232b065423bd2683d75ca177775fd352\",\"nl9br\":\"mBc3pEHKBiiPeAEpZRskug==71b353fed6403b99:c58099676beacc146c14867645e29783\"}]"""
if let obj = responseDataString?.toJSON() as? [[String:Any]] {
obj.forEach {
print($0["nl2br"])
}
}
Result
Optional(2019-05-02 19:52:10)
Optional(2019-04-26 21:36:32)
Optional(2019-04-26 21:20:24)
Optional(2019-04-10 23:57:17)
Optional(2019-02-22 21:38:16)
Edit: In json this
[{
"name":"ppp"
}]
is an array of dictionaries to be [[String:Any]] notice nested [[]] , while this
{
"name":"ppp"
}
is a dictionary represented by [String:Any] notice only []

Convert decrypted string into JSON object

After decrypting my response from API i am getting a string "name:DM100, profile:[1,2,4,5]".
How can i convert this to a json object where name is string and profile is an array
i have tried using but getting nil
if let data = testString.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print("JSON Serialization Error :-> \(error.localizedDescription)")
}
}
return nil
}
Your JSON String is not valid. It should look like this:
let testString = "{\"name\":\"DM100\", \"profile\":[1,2,4,5]}"
if let data = testString.data(using: .utf8) {
do {
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print(json["name"])
}
}
catch {
print(error.localizedDescription)
}
}
Start and end with curly braces {} and have double quotations around string keys and values.
You can use following code to get the output:
But String must have and valid JSON format first as follows:
let string = "{\"name\":\"DM100\", \"profile\":[1,2,4,5]}"
let data = string.data(using: .utf8)!
do {
if let jsonObj = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? Dictionary<String,Any> {
print(jsonObj)
} else {
print("JSON Error")
}
} catch let error as NSError {
print(error)
}

Convert Json string to Json object in Swift 4

I try to convert JSON string to a JSON object but after JSONSerialization the output is nil in JSON.
Response String:
[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]
I try to convert this string with my code below:
let jsonString = response.result.value
let data: Data? = jsonString?.data(using: .utf8)
let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String:AnyObject]
print(json ?? "Empty Data")
The problem is that you thought your jsonString is a dictionary. It's not.
It's an array of dictionaries.
In raw json strings, arrays begin with [ and dictionaries begin with {.
I used your json string with below code :
let string = "[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]"
let data = string.data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]
{
print(jsonArray) // use the json here
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
and I am getting the output :
[["form_desc": <null>, "form_name": Activity 4 with Images, "canonical_name": df_SAWERQ, "form_id": 3465]]
Using JSONSerialization always felt unSwifty and unwieldy, but it is even more so with the arrival of Codable in Swift 4. If you wield a [String:Any] in front of a simple struct it will ... hurt. Check out this in a Playground:
import Cocoa
let data = "[{\"form_id\":3465,\"canonical_name\":\"df_SAWERQ\",\"form_name\":\"Activity 4 with Images\",\"form_desc\":null}]".data(using: .utf8)!
struct Form: Codable {
let id: Int
let name: String
let description: String?
private enum CodingKeys: String, CodingKey {
case id = "form_id"
case name = "form_name"
case description = "form_desc"
}
}
do {
let f = try JSONDecoder().decode([Form].self, from: data)
print(f)
print(f[0])
} catch {
print(error)
}
With minimal effort handling this will feel a whole lot more comfortable. And you are given a lot more information if your JSON does not parse properly.
I tried the solutions here, and as? [String:AnyObject] worked for me:
do{
if let json = stringToParse.data(using: String.Encoding.utf8){
if let jsonData = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String:AnyObject]{
let id = jsonData["id"] as! String
...
}
}
}catch {
print(error.localizedDescription)
}
I used below code and it's working fine for me. :
let jsonText = "{\"userName\":\"Bhavsang\"}"
var dictonary:NSDictionary?
if let data = jsonText.dataUsingEncoding(NSUTF8StringEncoding) {
do {
dictonary = try NSJSONSerialization.JSONObjectWithData(data, options: [.allowFragments]) as? [String:AnyObject]
if let myDictionary = dictonary
{
print(" User name is: \(myDictionary["userName"]!)")
}
} catch let error as NSError {
print(error)
}
}
static func getJSONStringFromObject(object: Any?) -> String? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: object ?? DUMMY_STRING, options: [])
return String(data: jsonData, encoding: .utf8) ?? DUMMY_STRING
} catch {
print(error.localizedDescription)
}
return DUMMY_STRING
}

Deserialize JSON from String to object

I try to deseralize my JSON that look like this :
{
"access_token": "This_is_my_token"
"item01": "blabla"
"item02": "blabla"
...
}
and I want to save only access_token into a variable. Not a big deal.
For exemple, with PHP it is something really simple like:
<?php
$jsonObj = json_decode($jsonString);
$access_token = $jsonObj["access_token"];
?>
But it doesn't look this easy with Swift. I try many things but nothing works for me.
Here is the code I have:
dataString = String(data: data, encoding: .utf8)!
do {
let anyObj: AnyObject? = try JSONSerialization.jsonObject(with: dataString, options: JSONSerialization.ReadingOptions([])) as AnyObject
guard let access_token = anyObj?.firstItem as? [String: AnyObject]
else {return}
print(access_token)
} catch {
print("JSON Deserial. Error")
}
with this code, I can't manipulate anyObj like I do with $jsonObj in PHP, there is no way to do something like anyObj["access_token"]
How can I access to this item in the object ?
Thanks
You can simply call this function by passing your data here and it will return a dictionary. From that dictionary you can pick access_token value.
class func parseJsonToDictionary(data: Data) -> ([String:AnyObject]?,Error?) {
let _ = NSString(data: data, encoding:String.Encoding.utf8.rawValue)
do {
let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
return (JSONObject as? [String:AnyObject],nil)
} catch let error as NSError {
return (nil,error)
}
}
If you are having json string and not json data then you can use this method to convert it to dictionary.
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
let str = "{\"name\":\"James\"}"
let dict = convertToDictionary(text: str)
Later you can get value of access_token from dictionary.
Instead of casting anyObj to AnyObject try casting it to a dictionary of strings like
let anyObj: AnyObject? = try JSONSerialization.jsonObject(with: dataString, options: JSONSerialization.ReadingOptions([])) as [String:String]
Then you can get accessToken by using anyObj["access_token"]

Resources