How to parse part of json data into table - ios

How to parse following json which I want to parse only few part.
```
{
"head": {
"StatusValue": 200,
"StatusText": "Success"
},
"body": {
"Data": [
{
"payer_type_id": 1,
"payer_type": "Self Pay"
},
{
"payer_type_id": 2,
"payer_type": "Corporate"
},
{
"payer_type_id": 6,
"payer_type": "Insurance"
}
],
"RecordCount": 3,
"TotalRecords": null
}
}
How to parse only data inside Data key.
Expected result should be in following format
Date = [["payer_type_id": 1,"payer_type": "Self Pay"],["payer_type_id": 2,"payer_type": "Corporate"],["payer_type_id": 6,"payer_type": "Insurance"]]

You can use Codable protocol for your parsing .
Create Your Model
struct APIRootModel : Codable {
let head : HeaderModel
let body : BodyModel
}
struct HeaderModel :Codable{
let StatusValue : Int
let StatusText : String
}
struct BodyModel : Codable{
let Data : [DataModel]
}
struct DataModel : Codable{
let payer_type_id : Int
let payer_type : String
}
Decode your json using JSONDecoder()
let decoder = JSONDecoder()
do {
let rootModel = try decoder.decode(APIRootModel.self, from: jsonData)
print(rootModel.body.data)
} catch {
print(error)
}
Use [DataModel] for your tableview datasource.

Try this:
let jsonString = "your json string here"
let dictObject = getDictionaryFromJsonString(dictString: jsonString)
let bodyDict = dictObject["body"]
let dataArray = bodyDict["Data"]
func getDictionaryFromJsonString(dictString:String)->
[String: Any] {
do {
return try JSONSerialization.jsonObject(with:
dictString.data(using: String.Encoding.utf8,
allowLossyConversion: true)!, options:
JSONSerialization.ReadingOptions.allowFragments) as!
Dictionary
} catch {
return [:]
}
}

Related

Reading JSON properties without structure/model

How can we extract arrays from server response JSON strings?
The JSON object is serialized as such:
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json) // output below
}
} catch let error {
print(error.localizedDescription)
}
and the resulting output is:
["locations": <__NSArrayM 0x280e23f90>(
{
lat = "123.111111";
long = "1.111111";
},
{
lat = "123.222222";
long = "1.222222";
},
{
lat = "123.333333";
long = "1.333333";
}
),
"mobileNo": 55551234,
"clientID": 2123456789,
"date": 10082019,
"time": 1854]
How do we read the properties like mobileNo and clientID from the json variable, and more importantly, how do we place the locations array into an array or dictionary?
Thanks for any help.
Use JSONDecoder and Decodable.
Create response structure.
struct Model: Decodable {
struct Location: Decodable {
var lat: String
var long: String
}
var locations: [Location]
var mobileNo: Int
var clientId: Int
var date: Int
var time: Int
}
User JSONDecoder to decode
do {
if let response: Model = try JSONDecoder().decode(Model.self, for: data) {
print(response)
}
} catch let error {
print(error.localizedDescription)
}

Objects inside Array inside Object Swift

Can somebody help with parsing this kind of JSON object?
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
My code doesnt work
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
for case let announcment in json!["array"]{
guard let title = announcment["title"] as? String,
let description = announcment["desc"] as? String,
else{ return }
}
task.resume()
Thank in advance for any help!
Pretty-printing your JSON makes it easier to work through:
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
You need to get the array first. An array of dictionaries is of type [[String: Any]].
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
guard let announcements = json["array"] as? [[String: Any]]
else { return }
announcements.forEach { announcement in
guard let title = announcement["title"] as? String,
let description = announcement["desc"] as? String
else { return }
// Do something with the result
}
}
}
task.resume()
You can structure your data and make it Codable:
struct Root: Codable {
let array: [Announcement]
}
struct Announcement: Codable {
let title: String
let desc: String
}
let data = Data("""
{"array":[{"title":"","desc":""},{"title":"","desc":""},{"title":"","desc":""}]}
""".utf8)
do {
let announcements = try JSONDecoder().decode(Root.self, from: data).array
for announcement in announcements {
print(announcement)
}
} catch {
print(error)
}
This will print
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")

Serialize JSON string that contains escaped (backslash and double quote) Swift return Badly formed object

I have response string from the backend like this:
{
"status": "success",
"data": "{\"name\":\"asd\",\"address\":\"Street 1st\"}"
}
I think the problem was because the double quote (") in the data String. When I remove the double quote, the serialization was success. But the response is from backend and I have to deal with it.
Anyone can solve this problem?
Thank you.
Here is the playground code.
import Foundation
var jsonStr = """
{
"status": "success",
"data": "{\"name\":\"asd\",\"address\":\"Street 1st\"}"
}
"""
let data = jsonStr.data(using: .utf8)
if let d = data {
do {
let o = try JSONSerialization.jsonObject(with: d)
print(o)
} catch let e {
print(e)
}
} else {
print("DATA conversion ERROR")
}
First of all if you wrap the JSON in the literal string syntax of Swift 4 you have to escape the backslashes.
let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""
You got nested JSON. The value for key data is another JSON string which must be deserialized separately
let jsonData = Data(jsonStr.utf8)
do {
if let object = try JSONSerialization.jsonObject(with: jsonData) as? [String:String] {
print(object)
if let dataString = object["data"] as? String {
let dataStringData = Data(dataString.utf8)
let dataObject = try JSONSerialization.jsonObject(with: dataStringData) as? [String:String]
print(dataObject)
}
}
} catch {
print(error)
}
Or – with a bit more effort but – much more comfortable with the (De)Codable protocol
struct Response : Decodable {
private enum CodingKeys : String, CodingKey { case status, data }
let status : String
let person : Person
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(String.self, forKey: .status)
let dataString = try container.decode(String.self, forKey: .data)
person = try JSONDecoder().decode(Person.self, from: Data(dataString.utf8))
}
}
struct Person : Decodable {
let name, address : String
}
let jsonStr = """
{
"status": "success",
"data": "{\\"name\\":\\"asd\\",\\"address\\":\\"Street 1st\\"}"
}
"""
let jsonData = Data(jsonStr.utf8)
do {
let result = try JSONDecoder().decode(Response.self, from: jsonData)
print(result)
} catch {
print(error)
}
You have an error in your code ,as you write it in code like that """json""",
also
data is String not dictionary , so you will need to convert to data then JSONSerialization again
check code i add your response in Json file and parse it , and work correctly
So just write this in json file called it data.json
{
"status": "success",
"data": "{\"name\":\"asd\",\"address\":\"Street 1st\"}"
}
and use this :
guard let jsonFile = Bundle.main.path(forResource: "data", ofType: "json") else { return}
guard let data = try? Data(contentsOf: URL(fileURLWithPath: jsonFile), options: .mappedIfSafe) else {return}
if let response = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) {
print(response)
if let dataInDictionary = response as? [String:Any] , let addresData = dataInDictionary["data"] as? String {
if let jsonData = addresData.data(using: .utf8),
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as? [String:Any]{
print(dictionary)
}
}
}
Here is another example based on the answer #vadian
Swift 4 - Using Codable
This was the json that I received:
{
"error_code": 0,
"result": {
"responseData": "{\"emeter\":{\"get_realtime\":{\"voltage_mv\":237846,\"current_ma\":81,\"power_mw\":7428,\"total_wh\":1920,\"err_code\":0}}}"
}
}
The JSON part with backslashes is equal to this:
{
"emeter": {
"get_realtime": {
"voltage_mv": 237846,
"current_ma": 81,
"power_mw": 7428,
"total_wh":19201,
"err_code":0
}
}
}
And this was the code that I used:
import Foundation
class RealtimeEnergy: Codable {
let errorCode: Int
let result: ResultRealtimeEnergy?
let msg: String?
enum CodingKeys: String, CodingKey {
case errorCode = "error_code"
case result, msg
}
init(errorCode: Int, result: ResultRealtimeEnergy?, msg: String?) {
self.errorCode = errorCode
self.result = result
self.msg = msg
}
}
class ResultRealtimeEnergy: Codable {
let responseData: String
var emeter: Emeter
enum CodingKeys: String, CodingKey {
case responseData
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
responseData = try container.decode(String.self, forKey: .responseData)
let dataString = try container.decode(String.self, forKey: .responseData)
emeter = try JSONDecoder().decode(Emeter.self, from: Data(dataString.utf8))
}
}
class Emeter: Codable {
let emeter: EmeterClass
init(emeter: EmeterClass) {
self.emeter = emeter
}
}
class EmeterClass: Codable {
let getRealtime: GetRealtime
enum CodingKeys: String, CodingKey {
case getRealtime = "get_realtime"
}
init(getRealtime: GetRealtime) {
self.getRealtime = getRealtime
}
}
class GetRealtime: Codable {
let voltageMv, currentMa, powerMw, totalWh: Int
let errCode: Int
enum CodingKeys: String, CodingKey {
case voltageMv = "voltage_mv"
case currentMa = "current_ma"
case powerMw = "power_mw"
case totalWh = "total_wh"
case errCode = "err_code"
}
init(voltageMv: Int, currentMa: Int, powerMw: Int, totalWh: Int, errCode: Int) {
self.voltageMv = voltageMv
self.currentMa = currentMa
self.powerMw = powerMw
self.totalWh = totalWh
self.errCode = errCode
}
}

How can I decode JSON with array and more JSON inside?

I recently began with swift. I need decode the json on below.
The JSON has inside two more JSON the first one (validation) does not matter. The second one (result) has a JSON array inside (serviceCenter). I need the information of each servicenter. I try to use servicecenter as decodeable class to get a servicenter object, but as the JSON does not have the proper format I can't do it.
[
{
"validation": {
"bValid": true,
"sDescription": "Access true."
}
},
{
"result": {
"serviceCenter": [
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "3666",
"sVin": "6JDO2345",
"sMiles": "3666",
"bDamage": "1",
"dDateTime": "04-17-2018 9:38 AM"
},
{
"model": "F360",
"color": "Red",
"make": "Ferrari",
"sTag": "0010",
"sVin": "6JDO2347",
"sMiles": "80000",
"bDamage": "1",
"dDateTime": "04-17-2018 9:25 AM"
},
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "0009",
"sVin": "6JDO2345",
"sMiles": "25000",
"bDamage": "1",
"dDateTime": "04-17-2018 9:23 AM"
},
{
"model": "Vanquish",
"color": "Purple",
"make": "Aston Martin",
"sTag": "0003",
"sVin": "6JDO2345",
"sMiles": "20000",
"bDamage": "1",
"dDateTime": "04-12-2018 10:37 AM"
}
]
}
}
]
I try so much but i cant do it.
This its my code now, Could someone help me please
do {
let parseoDatos = try JSONSerialization.jsonObject(with: data!) as! [AnyObject]
let h = type(of: parseoDatos )
print("'\(parseoDatos)' of type '\(h)'")
let contenido = parseoDatos[1]["result"]
if let services = contenido!! as? Dictionary<String, Array<Any>> {
for (_,serviceArray) in services {
for sc in serviceArray{
let h = type(of: sc )
print("'\(sc)' of type '\(h)'")
}
}
}
} catch {
print("json processing failed")
}
the result of print sc is
{
bDamage = 1;
color = Purple;
dDateTime = "04-17-2018 9:38 AM";
make = "Aston Martin";
model = Vanquish;
sMiles = 3666;
sTag = 3666;
sVin = 6JDO2345;
}' of type '__NSDictionaryI'
You can use Codable
Initial response have array of InitialElement and InitialElement is is struct with validation , result , result may be nil
don't forget to add your URL at url
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let initial = try? JSONDecoder().decode([InitialElement].self, from: data){
// inital now have array of InitialElement and InitialElement is is struct with validation , result , result may be nil
print(initial)
}
}.resume()
With this Model for Data:
import Foundation
struct InitialElement: Codable {
let validation: Validation?
let result: ResultData?
}
struct ResultData: Codable {
let serviceCenter: [ServiceCenter]
}
struct ServiceCenter: Codable {
let model, color, make, sTag: String
let sVin, sMiles, bDamage, dDateTime: String
}
struct Validation: Codable {
let bValid: Bool
let sDescription: String
}
extension InitialElement {
init(data: Data) throws {
self = try JSONDecoder().decode(InitialElement.self, from: data)
}
}
try this code
enum ParsingError: Error {
case wrongFormat(String)
}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!)
guard let array = jsonObject as? [Any] else {
throw ParsingError.wrongFormat("wrong root object")
}
guard array.count == 2 else {
throw ParsingError.wrongFormat("array count != 2")
}
guard let dict = array[1] as? [String: Any] else {
throw ParsingError.wrongFormat("can't parse dict from array")
}
guard let serviceCenters = (dict["result"] as? [String: Any])?["serviceCenter"] else {
throw ParsingError.wrongFormat("can't parse serviceCenters")
}
guard let serviceCentersArray = serviceCenters as? [[String : Any]] else {
throw ParsingError.wrongFormat("serviceCenters is not an array")
}
print("\(type(of: serviceCentersArray))\n", serviceCentersArray)
} catch {
print("json processing failed: \(error)")
}
Thanks all for yours answers, it's my first question here, and i feels great all the help. Finally i can resolve the problem. Maybe not the best way, but here its the code:
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil{
print("error=\(String(describing: error))")
return
}
do {
let parseoDatos = try JSONSerialization.jsonObject(with: data!) as! [AnyObject]
let h = type(of: parseoDatos )
print("'\(parseoDatos)' of type '\(h)'")
let contenido = parseoDatos[1]["result"]
if let services = contenido!! as? Dictionary<String, Array<Any>> {
for (_,serviceArray) in services {
for sc in serviceArray{
let h = type(of: sc )
print("'\(sc)' of type '\(h)'")
let valid = JSONSerialization.isValidJSONObject(sc) // true
print(valid)
do {
let jsonData = try JSONSerialization.data(withJSONObject: sc, options: .prettyPrinted)
let serviceDecoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
if let scJSON = serviceDecoded as? [String:String] {
print ("--------------------------")
print("'\(scJSON)' of type '\(type(of: scJSON))'")
print ("--------------------------")
}
} catch {
print(error.localizedDescription)
}
i think later y try to use Codable as suggested, but for now the code is working ok. Thanks again!
//try this it is working
let arrayMain=try?JSONSerialization.jsonObject(with:jsonData!,options:.mutableLeaves) as! Array<Any>
//print(arrayMain!)
if let firstDictionart=arrayMain![0] as? [String: Any] {
if let insideFirstDict = firstDictionart["validation"] as? [String: Any]{
print(insideFirstDict["bValid"]!)
print( insideFirstDict["sDescription"]!)
}
}
if let resultDictionary=arrayMain![1] as? [String: Any] {
if let serviceDictionary = resultDictionary["result"] as? [String: Any] {
for array in serviceDictionary["serviceCenter"] as! Array<Any>{
if let infoDicti=array as? [String: Any] {
print( infoDicti["color"]!)
print( infoDicti["make"]!)
print( infoDicti["color"]!)
print( infoDicti["sTag"]!)
print( infoDicti["sVin"]!)
print( infoDicti["sMiles"]!)
print( infoDicti["sVin"]!)
print( infoDicti["model"]!)
print( infoDicti["bDamage"]!)
print( infoDicti["dDateTime"]!)
}
}
}
}

How do I decode JSON(JSON Web Token) in Swift 4?

How do I decode this json in Swift 4, with decoder?
I want to be able to get the "token" by itself, so I can store it in the Keychain.
{
"success":true,
"token":"***"
,
"user": {
"id": "59f0ec6d5479390345980cc8",
"username": "john",
"email": "john#gmail.com"
}
}
I have tried this, but it doesn't print anything.
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, _, _) in
guard let data = data else { return }
do {
let jsonwt = try JSONDecoder().decode(JWT.self, from: data)
print(jsonwt.token)
} catch {}
}
task.resume()
}
I can put this after the catch, but that gets the whole json, and I don't want that.
print(String(data: data, encoding: .utf8)!)
Here are the structures. I think this is where the problem lies.
struct User: Decodable {
let id: String
let username: String
let email: String
}
struct JWT: Decodable {
let success: String
let token: String
let user: User
}
Works like this:
struct User : Codable
{ var id : String
}
struct JWT : Codable
{ var success : Bool
var token : String
var user :User
}
let json = """
{ \"success\" : true,
\"token\" : \"***\",
\"user\":
{ \"id\": \"59f0ec6d5479390345980cc8\",
\"username\": \"john\",
\"email\": \"john#gmail.com\"
}
}
"""
let decoder = JSONDecoder()
let jwt = try decoder.decode(JWT.self, from: json.data(using: .utf8)!)
print ("token: \(jwt.token)")
Here's some playground code that demonstrates the code for parsing JSON in Swift:
//: Playground - noun: a place where people can play
import UIKit
import XCTest
import PlaygroundSupport
let json = """
{
"success":true,
"token":"***"
,
"user": {
"id": "59f0ec6d5479390345980cc8",
"username": "john",
"email": "john#gmail.com"
}
}
""".data(using: .utf8)!
do {
if let data = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String:Any], let token = data["token"] {
print("token is \(token)")
}
} catch _ {
print("Failed to decode JSON")
}

Resources