How Fix Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 52." - ios

How to Convert this one. "{\n ID = \"d9a7c7bf-781d-47b3-bb4e-e1022ec4ce1b\";\n Name = Headquarters;\n}"; To this format {
"ID": "d9a7c7bf-781d-47b3-bb4e-e1022ec4ce1b",
"Name": "Headquarters"
}
if let jsonString = text as? String {
let objectData = jsonString.data(using: String.Encoding.utf8)
do {
let json = try JSONSerialization.jsonObject(with: objectData!, options: .allowFragments) as! [String:Any] //try JSONSerialization.jsonObject(with: objectData!, options: JSONSerialization.ReadingOptions.mutableContainers)
print(String(describing: json))
return json
} catch {
// Handle error
print(error)
}
}
Blockquote

First of all and already mentioned the string format is clearly not JSON.
It's the string format which is returned when calling the description property of a Foundation collection type (NSArray / NSDictionary).
For example a print statement calls description and this format appears also in output of Terminal.app.
However there is a solution: This string format is called openStep (an OpenStep / NeXt legacy format) and is available in PropertyListSerialization
This code reads the format:
let string = "{\n ID = \"d9a7c7bf-781d-47b3-bb4e-e1022ec4ce1b\";\n Name = Headquarters;\n}"
let data = Data(string.utf8)
do {
let dictionary = try PropertyListSerialization.propertyList(from: data, format: nil)
print(dictionary)
} catch { print(error) }
Note:
I'm pretty sure that the original data format is not openStep and somewhere you created the string unnecessarily with the String(describing initializer like in the question.

your json format is incorrect. If you try it with jsonformatter it will throw this error:
so first you need to replace ; with ,. The second is that Strings should be wrapped in double quotes, replace Name = Headquarters with Name = "Headquarters".
This is the right form
{\n ID = \"d9a7c7bf-781d-47b3-bb4e-e1022ec4ce1b\",
\n Name = "Headquarters"\n}

Related

Unable to extract data properly from JSON in swift

I have a this kind of json object in my response after parsing json string to object
[
"requestId": 1,
"response": {
code = SUCCESS;
},
"messageId": ACTION_COMPLETE
]
I am trying to extract requestId using
responseMsg["requestId"] as! Int
I am getting this error
Could not cast value of type 'NSTaggedPointerString' (0x21877a910) to
'NSNumber' (0x218788588).
I tried it changing to Int(responseMsg["requestId"] as! String)!
This thing is working for positive numbers but not for negative numbers probably bcz when requestId = -2 it throws me an error
Could not cast value of type '__NSCFNumber' (0x21877a000) to
'NSString' (0x218788290).
I tried with different other solution too but did not work.
For parsing the JSON data, its better use Codable instead of manually parsing everything.
For JSON format,
{
"requestId": 1,
"response": {
"code":"SUCCESS"
},
"messageId": "ACTION_COMPLETE"
}
Create Models like,
struct Root: Decodable {
let requestId: String?
let messageId: String
let response: Response
enum CodingKeys: String, CodingKey {
case requestId, messageId, response
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if let id = try? values.decode(Int.self, forKey: .requestId) {
requestId = String(id)
} else if let id = try? values.decode(String.self, forKey: .requestId) {
requestId = id
} else {
requestId = nil
}
messageId = try values.decode(String.self, forKey: .messageId)
response = try values.decode(Response.self, forKey: .response)
}
}
Now, parse the JSON data using,
do {
let root = try JSONDecoder().decode(Root.self, from: data)
print(root.requestId) //access requestId like this....
} catch {
print(error)
}
Try
Int(String(describing: responseMsg["requestId"]))!
This ensures any data is converted to string first and then to int
This error message
Could not cast value of type 'NSTaggedPointerString' (0x21877a910) to 'NSNumber' (0x218788588).
tells us that the JSON request id is being parsed as a string. NSTaggedPointerString is a special internal type used by the ObjC runtime to represent strings.
Try this:
let requestId = responseMsg["requestId"] as! String
print("request id: \(requestId)") // Prints a string
Note, it may print something that looks like a number, but it isn't one.
The JSON you are parsing probably looks like
{
"requestId": "1",
"response": {
"code" = "SUCCESS"
},
"messageId": "ACTION_COMPLETE"
}
Note the 1 in quotes.
Swift 5
String interpolation is what worked for me! (casting it first to String didn't work as I had other values for which the json decoder actually did its job and cast them directly to a number)
if let responseMsg_any = responseMsg["requestId"],
let responseMsg_int = Int("\(responseMsg_any)") {
//..
}
Warning:
This solution allows any Type to become a String and be checked for a Int value. Only use this if you're not concerned about the value's Type prior to interpolation.

Swifty Json parsing

I am using SwiftyJson library for parsing my following json
{
"data": {
"id": "12345",
"messages": {
"message": "{\"data\":{\"msg\":\"HelloMsg\"}}"
}
}
}
I tried to use following code to get msg parameter
let json = JSON(data)
let msg = JSON(json["data"]["messages"]["message"])
msg["data"]["msg"].stringValue
However, I could not get the value of msg parameter. What shall I do to get HelloMsg?
The content of the "message" field is not parsed JSON, it's a JSON string.
Use SwiftyJSON's JSON(parseJSON:) initializer to accept a string as input and parse it as JSON:
let messages = json["data"]["messages"]["message"].stringValue
let innerJSON = JSON(parseJSON: messages)
let msg = innerJSON["data"]["msg"].stringValue // "HelloMsg"
The error occurs because JSON(...) is the wrong API to initialize and parse a SwiftyJSON object from a string.
You have to use this syntax:
let json = JSON(data)
let msg = JSON(parseJSON: json["data"]["messages"]["message"].stringValue)
msg["data"]["msg"].stringValue
From the documentation of init(_ object: Any):
note: this does not parse a String into JSON, instead use init(parseJSON: String)
Edit:
To test the code in a Playground
let str = """
{"data": {"id": "12345",
"messages": {
"message": "{\\"data\\":{\\"msg\\":\\"HelloMsg\\"}}"
}
}
}
"""
let data = Data(str.utf8)
let json = JSON(data)
let msg = JSON(parseJSON: json["data"]["messages"]["message"].stringValue)
msg["data"]["msg"].stringValue
The JSON as traditional literal string is
let str = "{\"data\": {\"id\": \"12345\",\"messages\": {\"message\": \"{\\\"data\\\":{\\\"msg\\\":\\\"HelloMsg\\\"}}\"}}}"
The messaage is a string. not a JSON. so SwiftyJson could not parse it. You will have to first parse that string and than get the message from that using JSONSerialization.jsonObject(with: Data, options: JSONSerialization.ReadingOptions).
You can refer to this answer to get the dictionary from that string: https://stackoverflow.com/a/30480777/7820107
Your second "message" key value is a String with a dictionary in JSON format, so you need to convert that string to JSON and access to ["data"]["msg"] then
Code
let json = JSON(data)
let msg = json["data"]["messages"]["message"]
let jsonFromString = JSON(data: msg.data(using: .utf8)!, options: JSONSerialization.ReadingOptions.allowFragments, error: nil)
debugPrint(jsonFromString["data"]["msg"])
Output
HelloMsg

how to parse the json using alamofire in swift 2?

I am having trouble with parsing json using alamofire (it is working fine using browser or postman),below is my code
Alamofire.request(.POST, reqStr.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! , parameters: nil).responseJSON { response in
GMDCircleLoader.hideFromView(self.view, animated: false)
if let dict = response.result.value {
self.selectArray = dict as! NSArray as! [NSDictionary]
if self.selectArray.count == 0 {
}else{
self.selectProperty.hidden = false
}
}
}
i am getting below error Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 14." UserInfo={NSDebugDescription=Invalid value around character 14.}
and searched a lot some body suggested that use responseString instead of responseJSON, if i use responseString i am getting data but in string format like
"{"Properties":[{ "ID":"22", "post_title":"Test Property" },{ "ID":"24", "post_title":"TestProperty" }]}"
how can convert it to Dictionary i used below code
if let dict = response.result.value
self.resulArray = dict as! [NSDictionary];
BUt it is crashing.
1)is their any way to get the results using responseJSON.
2) if i use responseString how to get convert to dictinary.
thanks in advance , I am new in Swift i am using swift2.0.

Create a JSON String in Swift

I send the text from a TextView to my Backend. To include linebreaks, i try to serialize the textView.text to JSON.
let jsonObject: NSMutableDictionary = NSMutableDictionary()
jsonObject.setValue(textView.text, forKey: "text")
let jsonData: NSData
do {
jsonData = try JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions()) as NSData
let jsonString = NSString(data: jsonData as Data, encoding: String.Encoding.utf8.rawValue) as! String
print(jsonString)
} catch _ {
print ("JSON Failure")
}
}
But since this is a Dictionary, the resulting text looks like this:
{"text":"test\nstack\n\noverflow"}
i actually just need: test\nstack\n\noverflow
Is there a pretty way to transform a multiline String in swift to have these "\n" for linebreaks without any extra characters?
Edit:
I expect to type into my textView something like this:
and as a result get the string "hello\n\n"
The source looks like this:
let text = textView.text
let components = text?.components(separatedBy: CharacterSet.newlines).filter({!$0.isEmpty})
let textWithLineFeeds = components?.joined(separator:"\n")
print(textWithLineFeeds!)
print(textView.text)
the first print gives:
test
hello
linebreak above
the second print statement:
test
hello
linebreak above
i wish i could see:
test\nhello\n\nlinebreak above
To convert text with arbitrary new line characters (CR, LF, CRLF etc.) to distinct - only LF - line breaks use:
let text = "test\r\nstack\n\noverflow\rfoo"
let components = text.components(separatedBy: CharacterSet.newlines).filter({!$0.isEmpty})
let textWithLineFeeds = components.joined(separator:"\n")
If the server accepts only CR, change \n to \r.

Xcode swift download binary file from json

I have json rpc service, one method gives binary file with metadata, for example:
{
id = 1;
jsonrpc = "2.0";
result = {
anonymized = 0;
id = 331210;
logged = 1;
content = "e1xydGYxXGFkZWZsYW5nM… …AwMDAwMDAwMDAwMH19";
};
}
On client side I can correctly deserialize response by:
let responseObject = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as? NSDictionary
I can read object result as NSDictionary, but can not find way to save field content to disk as binary file. I did not find any solution.
Thanks for your help.
Ok, so content looks like it's base64 encoded. If so, you would do it like this:
if let encodedData = responseObject?["result"]?["content"] as? String {
if let data = NSData(base64EncodedString: encodedData, options: nil) {
data.writeToFile(desiredFilePath, atomically: true)
}
}

Resources