How to json with array and string in swift 3 - json

I want to make json like this.
timings = [{"day":"Monday","from":"01:00pm","to":"04:00pm"},{"day":"Tuesday","from":"01:00pm","to":"04:00pm"}],
The day is array and (from) and (to) is string value.
I use this code.
let myjson = Category.map({ ["": $0] })
Category is array.

let phoneNumbersDictionary = yourArray.map({ ["day": $0 , "to" :txt_timing_to.text! , "from":txt_timing_from.text!] })
let JSON = try? JSONSerialization.data(withJSONObject: phoneNumbersDictionary, options: [])
if let JSON1 = JSON
{
print(String(data: JSON1, encoding: String.Encoding.utf8)!)
}

Related

Use Swift Decoder to pull attributes from JSON array

I have a JSON array created using this call:
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] else {
print("This is not JSON!!!")
return
}
I am trying to get elements from the JSON objects in the array to display them using the following code:
struct sWidget: Codable{
var createdBy: String
var createdDate: Date
var status: String
var widgetNumber: String
var updatedBy: String
var updatedDate: Date
}
do {
let decoder = JSONDecoder()
for (index, value) in json.enumerated() {
let currentWidget = try decoder.decode(sWidget.self, from: json[index] as! Data)
let currentNum = currentWidget.widgetNumber
//print(currentNum)
widgetNums.append(currentNum)
}
}
catch {
print("decoding error")
}
The code compiles but when I run it I get this error in the output:
Could not cast value of type '__NSDictionaryM' (0x1063c34f8) to
'NSData' (0x1063c1090). 2018-08-09 09:41:02.666713-0500
TruckMeterLogScanner[14259:1223764] Could not cast value of type
'__NSDictionaryM' (0x1063c34f8) to 'NSData' (0x1063c1090).
I am still investigating but any tips would be helpful.
Did you try that fetching objects like above mentioned? Because i see that you are using Codable. Fetching is very simple with that actually.
let yourObjectArray = JSONDecoder().decode([sWidget].self, data: json as! Data)
May be this line can be buggy but you can fetch them with one line.
Extending #Cemal BAYRI's answer:
JSONDecoder() throws, so make sure to either us try? or try (don't forget do-catch with try)
guard let data = content as? Data else {
return [sWidget]()
}
let jsonDecoder = JSONDecoder()
1. try?
let yourObjectArray = try? jsonDecoder.decode([sWidget].self, data: data)
2. try
do {
let yourObjectArray = try jsonDecoder.decode([sWidget].self, data: data)
} catch let error {
}
Note: You would need to take care of Data and Date formatting. Below is an example for Date:
jsonDecoder.dateDecodingStrategy = .iso8601
You can also check it out here

Accessing JSON data with Swift

I have an array of JSON data from the following call:
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] else {
print("Not containing JSON")
return
}
when I run print(json) I get the following in the output:
[{
"CREATED_BY" = "DOMAIN\\USER";
"CREATED_DATE" = "2016-11-28T08:43:59";
STATUS = U;
"WIDGET_NUMBER" = K11;
"UPDATED_BY" = "<null>";
"UPDATED_DATE" = "<null>";
}, {
"CREATED_BY" = "DOMAIN\\USER";
"CREATED_DATE" = "2016-05-09T08:46:23";
STATUS = U;
"WIDGET_NUMBER" = 89704;
"UPDATED_BY" = "<null>";
"UPDATED_DATE" = "<null>";
}]
I am trying to get all of the WIDGETNUMBER values in the array of JSON data. The json variable is a Any type and I have not been able to convert to a struct so far. Is there an easy way to get the elements from the JSON objects?
It looks like you have an array of dictionaries
for item in json {
if let item = item as? [String: Any], let widgetNo = item["WIDGET_NUMBER"] {
print(widgetNo)
}
}
Your content is array of Dictionary, so that you must convert each element Dictionary to Json
for dic in content {
do {
let jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
print(jsonData)
} catch {
print(error.localizedDescription)
}
}
Or you can read value of WIDGET_NUMBER direct from Dictionary
for dic in content {
print(dic["WIDGET_NUMBER"] ?? "Not found")
}
Joakim's answer is spot on for getting the widget number. For your struct, be sure to add something like this as an initializer to map your object.
let widgetNumber: Int
let user: String
init?(json:[String:Any]) {
guard let widgetNumber = json["WIDGET_NUMBER"] as? Int,
let user = json["CREATED_BY"] as? String else { return nil }
self.widgetNumber = widgetNumber
self.user = user
}
If you just want an array of widget numbers you could use the reduce function which iterates the dictionaries in the array and extracts the widget numbers:
Using your data I put this in a storyboard:
let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as! [[String: Any]]
let widgetNumbers = json?.reduce(into: [String]()){ (accum, dict) in
guard let widget = dict["WIDGET_NUMBER"] as? String else { return }
accum.append(widget)
}
widgetNumbers // -> ["K11", "89704"]

How to convert dictionary to json string without space and new line

I am trying to convert a dictionary to json string without space and new line. I tried to use JSONSerialization.jsonObject but I still can see spaces and new lines. Is there any way to have a string result looks something like this
"data": "{\"requests\":[{\"image\":{\"source\":{\"imageUri\":\"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png\"}},\"features\":[{\"type\":\"LOGO_DETECTION\",\"maxResults\":1}]}]}"
My conversion
var features = [[String: String]]()
for detection in detections {
features.append(["type": imageDetection[detection]!])
}
let content = ["content": base64Image]
let request = ["image": content, "features": features] as [String : Any]
let requests = ["requests": [request]]
let jsonData = try! JSONSerialization.data(withJSONObject: requests, options: .prettyPrinted)
let decoded = try! JSONSerialization.jsonObject(with: jsonData, options: [])
print(decoded)
Result
{
requests = (
{
features = (
{
type = "LABEL_DETECTION";
},
{
type = "WEB_DETECTION";
},
{
type = "TEXT_DETECTION";
}
);
image = {
content = "iVBO
...........
You are decoding the serialized JSON into an object. When an object is printed into the console, you will see the indentation, and the use of equals symbols and parentheses.
Remove the .prettyPrinted option and use the data to initialize a string with .utf8 encoding.
let jsonData = try! JSONSerialization.data(withJSONObject: requests, options: [])
let decoded = String(data: jsonData!, encoding: .utf8)!

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]

SwiftyJSON looping through an array of JSON objects

[
{
"cont": 9714494770,
"id": "1",
"name": "Kakkad"
},
{
"cont": 9714494770,
"id": "2",
"name": "Ashish"
}
]
The one above is a json array filled with JSON objects. I don't know how to parse through this with SwiftyJSON
Example from the SwiftyJSON page, adapted to your data:
let json = JSON(data: dataFromNetworking)
for (index, object) in json {
let name = object["name"].stringValue
println(name)
}
Assuming [{"id":"1", "name":"Kakkad", "cont":"9714494770"},{"id":"2", "name":"Ashish", "cont":"9714494770"}] is assigned to a property named jsonData.
let sampleJSON = JSON(data: jsonData)
let sampleArray = sampleJSON.array sampleArray is an optional array of JSON objects.
let firstDict = sampleArray[0] firstDict is an optional JSON dict.
let name = firstDict["name"] is an optional JSON object
let virtName = name.string is a optional string (In this case "Kakkad").
let realName = name.stringValue realName is a string or an empty string.
You could also use:
let longName = sampleJSON[0]["name"].stringValue
After you initialize the JSON object with data all of the elements are JSON types until you convert them to a swift type.
.string optional (string or null)
.stringValue string or "" empty
string
.dict optional ([String: AnyObject] or null)
.dictValue
([String: AnyObject] or String: AnyObject)
For Swift4 I have updated the code from Moritz answer
if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
let optData = try? JSON(data: data as Data)
guard let json = optData else {
return
}
//If it is a JSON array of objects
for (_, object) in json {
let name = object["name"].stringValue
print(name)
}
}
}
Swift 3 or 4 code like this:
let json = JSON(yourData)
for (_, object) in json {
let cont = object["cont"].stringValue
print(cont)
}
You can put index instead of _ if you use is anywhere in your code. If you don't use a variable, it's better to put _ (XCode also gives warnings).