Unable to use SwiftyJSON to access JSON data - json

I'm trying to access some JSON data but I can't access that using swiftyJSON. I'm getting JSON response back so I'm acquiring it using alamofire. Here's the JSON:
{"groupID":"6","groupName":"Test","teacher":"teacher1
","teacherID":"13","Locations":
[{"locationID":"5","locationName":"field"},
{"locationID":"6","locationName":"34th"}],"Error":""}
I'm using print statements to debug what's wrong. Here's the code that I'm trying to use:
let json = JSON(response.result.value ?? "error")
//let jsonError = json["Error"]
print("=================<JSON RESPONSE>=================");
print(json)
print("=================</JSON RESPONSE/>=================");
self.groupID = json["groupID"].stringValue
self.groupName = json["groupName"].stringValue
self.teacherID = json["teacherID"].stringValue
let locjson = json["Locations"]
print("Entering LocJSON Loop")
print("=================<LOCJSON >=================");
print("GNAME:" + self.groupID)
print("TID: " + json["teacherID"].stringValue)
print("Locjson.stringalue: " + locjson.stringValue)
//print("LocationJSON" + json["Locations"]);
print("=================</LOCJSON/>=================");
for (key, object) in locjson {
print("In LocJSON Loop")
let locationIDVar: Int? = Int(key)
self.locations[locationIDVar!].locationID = locationIDVar!
self.locations[locationIDVar!].locationName = object.stringValue
print(self.locations[locationIDVar!].locationName)
print(object);
}
Here's the output from console that corresponds to the print statements.
=================<JSON RESPONSE>=================
{"groupID":"6","groupName":"Test","teacher":"Teacher1"
,"teacherID":"13","Locations":
[{"locationID":"5","locationName":"field"},
{"locationID":"6","locationName":"34th"}],"Error":""}
=================</JSON RESPONSE/>=================
Entering LocJSON Loop
=================<LOCJSON >=================
GNAME:
TID:
Locjson.stringalue:
=================</LOCJSON/>=================
Also, how do I get to the multiple locations that are inside 'Locations'?

The value for key Locations is an array containing dictionaries.
let locjson = json["Locations"].arrayValue
for location in locjson {
let locID = location["locationID"].stringValue
let locName = location["locationName"].stringValue
print(locID, locName)
}
In Swift 4 I'd prefer Decodable over SwiftyJSON because you can directly decode into structs.

Related

Parse JSON Data in Swift from API Call "Value of type 'Any?' has no subscripts"

I am trying to parse some JSON data returned from an API call. The path I want to navigate is media > faces > tags. When I navigate to media it works, but when I add faces i receive the "Value of type 'Any?' has no subscripts" error.
I know this has been covered before on Stackoverflow but I can't seem to find out what is wrong. Any help is appreciated!
let dictionary = try JSONSerialization.jsonObject(with: data!, options:.mutableContainers) as? [String:Any];
// print(dictionary!["media"]) //this line works
print(dictionary!["media"]["faces"]) // this line does not work
The API returned data looks something like this
Optional({
checksum = 44efb3256385bfe62425c5fde195a3352e814ff6d900058e47a07b2cd7654252;
duration = "00:00:00";
faces = (
{
angle = "1.2222";
"appearance_id" = 0;
"detection_score" = 1;
duration = "00:00:00";
"face_uuid" = "78338d20-9ced-11ea-b153-0cc47a6c4dbd";
height = "74.31999999999999";
"media_uuid" = "fec83ac3-de00-44f0-ad5b-e1e990a29a8c";
"person_id" = "";
points = (
{
name = "basic eye left";
type = 512;
x = "85.16";
y = "86.62";
},
You need to cast the value returned from dictionary!["media"] as another Dictionary to be able to do this. Try this:
if let data = data,
let dictionary = try JSONSerialization.jsonObject(with: data, options:.mutableContainers) as? [String: Any],
let media = dictionary["media"] as? [String: Any] {
print(media["faces"])
}

Remove unwanted data from JSON using swift

I am getting response
{"msg":"Success: Mobile Number is Valid","status":0}396b6c706a54383638343131
How can I get valid JSON from my API response using swift I am getting JSON error.
Code:
NSLog("Login response: " + response, "response")
let jsonTag = JSON(response.dropLast(24).data(using: .utf8)!)
let loginModelRootClass = LoginModelRootClass(fromJson: jsonTag )
if (loginModelRootClass.status == 0)
{
/* successfully login */
NSLog("Login response: " + loginModelRootClass.msg, "response")
}
else
{
/* failure login */
NSLog("Login response: " + loginModelRootClass.msg, "response")
New to swift please help.
I agree with the comments that the best option is to get the backend to send valid json. However if that is not possible, you could use the function below to remove the invalid trailing data and then decode with Codable
func clean(json: String) -> String? {
guard let closing = json.lastIndex(of: "}") else {return nil}
var string = json
let range = string.index(after: closing)..<string.endIndex
string.removeSubrange(range)
return string
}

Parsing JSON with Swift (NSArray)

I'm trying to parse a JSON file in Xcode with Swift 3. My problem is getting the "values", 14.2. The error I get is "Type Any has no subscript member".
Here is my NSArray (Aka firstIndex):
{
level = 2;
levelType = hl;
name = t;
unit = Cel;
values = (
"14.2"
);
}
Here is my code:
if let parameters = test["parameters"] as? NSArray {
let firstIndex = parameters[0]
//print(firstIndex)
PROBLEM --> if let values = firstIndex["values"] as? Int {
}
}
The value for key values is also an array, represented by the parentheses.
The error occurred because NSArray does not provide type information.
In Swift use always native Array (here [[String:Any]]).
if let parameters = test["parameters"] as? [[String:Any]], let firstIndex = parameters.first {
if let values = firstIndex["values"] as? [String], let firstValue = values.first {
print(firstValue) // or Double(firstValue)!
}
}

Turning json variables into swift variables

My PHP server-side returns a JSON like this:
[{"scan_status":"ok","visitorData":[{"visitorCompany":"xyl","visitorStreet":"street","visitorBranche":"health","visitorEmail":"wesweatyoushop#gmail.com","lastmodified":"2014-12-15 14:18:55"}]}]
Now in Swift I would like to store this data, and for this I am trying to parse the data into Swift variables, however I got stuck.
do {
//check wat we get back
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves )
let vData = jsonData[0]["visitorData"]
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
This prints
Test vData: Optional(( { visitorStreet = street; visitorPhone = 01606478; visitorCompany = xyl; visitorBranche = Sports; visitorEmail = "health#gmail.com"; lastmodified = "2014-12-15 14:18:55"; } ))
but when I try to get visitorCompany with
let vCompany = vData["visitorCompany"]
I get a compile error:
Cannot subscript a value of type 'AnyObject?!' with an index of type 'String'
BTW, why do we see the equals sign in swift i.e. visitorStreet = street?
This is because the compiler doesn't know the type of your decoded objects.
Help the compiler using casting with if let:
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves )
if let vData = jsonData[0]["visitorData"] as? [[String:AnyObject]] {
if let vCompany = vData[0]["visitorCompany"] {
print(vCompany)
}
}
}
let vData = jsonData[0]["visitorData"] populates vData with a generic AnyObject?, because Swift can't know what kind of objects PHP returns in the JSON.
You need to do a an optional cast to another dictionary before you can use vData like you want: jsonData[0]["visitorData"] as? [String:AnyObject].
And because a conditional cast returns an optional, it's best you do an optional binding to unwrap that optional, resulting in a code similar to this:
if let vData = jsonData[0]["visitorData"] as? [String:AnyObject] {
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
Or even better, as jsonData can not be an array, or it could be an empty array (the server malfunctions and sends an invalid json for example), you can go even further with the validation:
if let items = jsonData as? [[String:AnyObject]], vData = items.first?["visitorData"] {
//let vCompany = vData["visitorCompany"]
print("Test vData: \(vData)")
}
items = jsonData as? [[String:AnyObject]] fails if jsonData is not an array, while vData = items.first?["visitorData"] fails if items.first is nil (optional chaining here), or if items.first doesn't have a visitorData key.
Try with this:
let vData = jsonData[0]["visitorData"]![0] as! [String:AnyObject]

NSJSONSeralization.dataWithJSONObject crashing

I have trouble with the NSJSONSeralization.dataWithJSONObject.
This will make my application crash:
#IBAction func sendMessage(sender: AnyObject) {
cachedMessage = messageField.text
messageField.text = ""
let messageData = NSJSONSerialization.dataWithJSONObject(cachedMessage, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
...
}
I hope you can somehow help me...
It will give you an error like : Invalid top-level type in JSON write
If you are trying to create a JSON object then it should be either from Array or Dictionary. Because An object that you want convert in to JSON Must be a Top Level object.
The top level object is an NSArray or NSDictionary.
Try in this way :
var demoArray : NSArray! // (Use it if you want to send data as an Array)
var demoDic : NSDictionary! // (Use it if you want to send data as an Dictionary (Key - Value Pair))
var cachedMessage : String!
cachedMessage = "Sample" // Here your String From textfield
demoArray = [cachedMessage] // Array with your string object
demoDic = ["Your Key":cachedMessage] // Dic with your string object.
You can provide your desired key instead of Your Key
This is how you can create Data from array and Dictionary.
let msgDataOfArray = NSJSONSerialization.dataWithJSONObject(demoArray, options: NSJSONWritingOptions.PrettyPrinted, error:nil)
let msgDataOfDic = NSJSONSerialization.dataWithJSONObject(demoDic, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
If you want to see how your data will look after JSONSerialization process then you can see like below way
var DataToStringForArray = NSString(data: msgDataOfArray!, encoding: NSUTF8StringEncoding)
var DataToStringForDic = NSString(data: msgDataOfDic!, encoding: NSUTF8StringEncoding)
println("Data To String OF Array : \(DataToStringForArray)")
println("Data To String OF Dic : \(DataToStringForDic)")