How To Filter JSON data parser - json

JSON response
tranArr
[{
"total_amt" : -10000,
"tran_type" : "C3",
"pay_type" : "05",
"tran_time" : "20180125 133122",
"point_total" : 0
},
{
"total_amt" : -1004,
"tran_type" : "C5",
"pay_type" : "05",
"tran_time" : "20180124 163602",
"point_total" : 0
}]
=====================
I want to filter tran_type = "C3"
What should I do?
"total_amt" : -10000,
"tran_type" : "C3",
"pay_type" : "05",
"tran_time" : "20180125 133122",
"point_total" : 0

Try something like this:
let string = "[{ \"total_amt\" : -10000,\"tran_type\" : \"C3\", \"pay_type\" : \"05\", \"tran_time\" : \"20180125 133122\", \"point_total\" : 0},{\"total_amt\" : -1004,\"tran_type\" : \"C5\", \"pay_type\" : \"05\", \"tran_time\" : \"20180124 163602\", \"point_total\" : 0 }]"
// Convert string to Data
let jsonData = string.data(using: .utf8)!
do {
// Serialize the json Data and cast it into Array of Dictionary
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [[String: Any]]
// Apply filter on `tran_type`
let tranArr = jsonObject?.filter({ (dictionary) -> Bool in
dictionary["tran_type"] as? String == "C3"
})
print(tranArr)
} catch {
print(error)
}
Filtered result will be in tranArr object.

Related

Swift Dynamic json Values Reading and Writing

Problem Stuck On
I am trying to be able to read out my json file data to the console log for testing so I can use it later on.
Im not sure how to finish off my other structs due to varying data size and possible bad json format.
Once I finish that I believe I would need to use a for loop for read the varying size of data from "M", "S" and "WP" (This part shouldn't be complicated I believe)
Possible Things to Consider
I want to write and add data to "M" "S" "WP"
The data amount for ("M", "S") could be any number of String Array data objects
The data in "WP" Might need a different format I would like to add a name("abc") with a Int array containing any number of data points
Note: My Json Format Might Be Wrong in Some Areas concerning MP and WP
Swift Code To Grab Data
import Foundation
struct UserDay: Codable {
let mp: UserMP
let wp: UserWP
}
struct UserMP: Codable {
let m: [UserM]
let s: [UserS]
}
struct UserM : Codable {
let title: String
let description: String
let time: String
}
struct UserS : Codable {
let title: String
let description: String
let time: String
}
struct UserWP: Codable {
let wp: [WPData]
}
struct WPData: Codable {
let title: String
let values: [Int]
}
class LogDataHandler {
public func grabJSONInfo(){
guard let jsonURL = Bundle(for: type(of: self)).path(forResource: "LogData", ofType: "json") else { return }
guard let jsonString = try? String(contentsOf: URL(fileURLWithPath: jsonURL), encoding: String.Encoding.utf8) else { return }
// Print Info for TESTING
var year: UserDay?
do {
year = try JSONDecoder().decode(UserDay.self, from: Data(jsonString.utf8))
} catch {
print("ERROR WHEN DECODING JSON")
}
guard let results = year else {
print("YEAR IS NIL")
return
}
print(results)
}
}
JSON Example Data Below
{
"01/01/2020": {
"MP" : {
"M" : [
{"title" : "m1", "description" : "1", "time" : "12:30pm"},
{"title" : "m2", "description" : "2", "time" : "1:30pm"},
{"title" : "m3", "description" : "3", "time" : "2:30pm"}
],
"S" : [
{"title" : "s1", "description" : "1", "time" : "1pm"}
]
},
"WP" : [
{ "title" : "abc", "values" : [12, 10, 6]},
{ "title" : "def", "values" : [8]}
]
},
"01/29/2020": {
"MP" : {
"M" : [{"title" : "m1", "description" : "1", "time" : "12:30pm"}],
"S" : [{"title" : "s1", "description" : "1", "time" : "12:30pm"}]
},
"WP" :[{ "title" : "def", "values" : [8]}]
}
}
Based on the comments and our chat, this seems to be a question of the right way to construct the Swift models and the JSON object.
Based on your (updated) JSON, you might want to decode your data into a [String: UserDay] - a dictionary with a date string as key and UserDay as a value.
First, WP property in your JSON is just an array of objects (that map to WPData), so it's best to change your UserDay.wp to be [WPData] instead of UserWP:
struct UserDay: Codable {
let mp: UserMP
let wp: [WPData] // <-- changed
}
Second, some of your models' properties don't match directly to what's in JSON because keys-properties mapping is case sensitive. You can explicitly define CodingKeys to map them:
struct UserDay: Codable {
let mp: UserMP
let wp: [WPData]
enum CodingKeys: String, CodingKey {
case mp = "MP", wp = "WP"
}
}
struct UserMP: Codable {
let m: [UserM]
let s: [UserS]
enum CodingKeys: String, CodingKey {
case m = "M", s = "S"
}
}
Now you're ready to decode [String: UserDay]:
let userDays = try JSONDecoder().decoder([String: UserDay].self, from: jsonData)
let userDay = userDays["01/29/2020"]
Of course, working with String instead of Date isn't very convenient. Unfortunately, Dictionary's conformance to Codable only supports Int or String as keys (AFAIK).
So, let's do a manual decoding into a new root object UserData that works with Dates:
struct UserData: Codable {
var userDays: [Date: UserDay]
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let dict = try container.decode([String: UserDay].self)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
// decode (String, UserDay) pairs into an array of (Date, UserDay)
let pairs = dict.compactMap { (key, value) -> (Date, UserDay)? in
guard let date = dateFormatter.date(from: key) else { return nil }
return (date, value)
}
// uniquing is used just in case there non unique keys
self.userDays = Dictionary(pairs, uniquingKeysWith: {(first, _) in first})
}
}
Now, we can decode into this UserData object:
let userData = try JSONDecoder().decode(UserData.self, from: jsonData)
let todaysData = userData.userDays[Date()]

Having trouble decoding retrieved JSON object in Swift

I am able to retrieve some JSON from an endpoint but then when I try to decode that JSON into my model object something goes wrong to where the json can't be parsed. I've made sure the properties in my model object matched the json keys, so I dont understand what the issue is. It prints out the catch block every time.
Here is my code to retrieve the json:
func getServiceProviders() {
let session = URLSession.shared
let url = URL(string: "http://exampleendpoint.com/example")!
URLSession.shared.dataTask(with: url) { data, response, error in
//Here is where I try to decode the json into my model object
do {
let jsonContent = try JSONDecoder().decode(ServiceObject.self, from: data!)
print(jsonContent)
} catch {
print("Ooops")
}
}.resume()
Here is my model object:
struct ServiceObject: Decodable {
let serviceproviders: [ServiceProvider]
struct ServiceProvider: Decodable {
let city: String
let coordinates: Location
let name: String
let overallGrade: String
let postalCode: Int
let state: String
let reviewCount: Int
}
struct Location: Decodable {
let latitude: Double
let longitude: Double
}
}
Here is what the json object I retrieve looks like:
{
"serviceproviders": [
{
"city" : "Beech Grove",
"coordinates" : {
"latitude" : "39.715417",
"longitude" : "-86.095646"
},
"name" : "William J Ciriello Plumbing Co Inc",
"overallGrade" : "A",
"postalCode" : "46107",
"state" : "Indiana",
"reviewCount" : 309
},
{
"city" : "Indianapolis",
"coordinates" : {
"latitude" : "39.922607",
"longitude" : "-86.0267094"
},
"name" : "Roby's Plumbing & Appliance Service",
"overallGrade" : "B",
"postalCode" : "46256",
"state" : "Indiana",
"reviewCount" : 903
},

JSON Decoding Error - typeMissmatch Swift 4

I'm trying to parse some data from JSON, I already got that working with another API but now I have another struct and I'm getting typeMissmatch Erros...
The JSON looks like:
{
"status": 200,
"data": {
"date": "2018-04-07T00:00:00.508Z",
"featured": [
{
"id": "2345",
"name": "name",
"price": "1,000",
"priceIcon": "String",
"priceIconLink": "URLString",
"images": {
"icon": "URLString",
"png": "URLString",
"gallery": "URLString",
"featured": "URLString"
},
"rarity": "1String",
"type": "1String",
"readableType": "1String"
}
],
"daily": [
{
"id": "12324",
"name": "name",
"price": "1,500",
"priceIcon": "String",
"priceIconLink": "URLString",
"images": {
"icon": "URLString",
"png": "URLString",
"gallery": "URLString",
"featured": "URLString"
},
"rarity": "1String",
"type": "1String",
"readableType": "1String"
}
]
}}
And a Codable struct like that:
struct Base : Codable {
let status : Int
let data : DataItems
}
struct DataItems : Codable {
let date : String
let featured : [Featured]
let daily : [Daily]
}
struct Featured : Codable {
let id : String
let name : String
let price : String
let priceIcon : String
let priceIconLink : String
let images : Images
let rarity : String
let type : String
let readableType : String
}
struct Daily : Codable {
let id : String
let name : String
let price : String
let priceIcon : String
let priceIconLink : String
let images : Images
let rarity : String
let type : String
let readableType : String
}
struct Images : Codable {
let icon : String
let png : String
let gallery : String
let featured : String
}
But when I try to decode that Json I get a "Swift.DecodingError.typeMismatch" Error:
▿ Swift.DecodingError.typeMismatch
▿ typeMismatch: (2 elements)
- .0: Swift.String #0
▿ .1: Swift.DecodingError.Context
▿ codingPath: 5 elements
- CodingKeys(stringValue: "data", intValue: nil)
- CodingKeys(stringValue: "daily", intValue: nil)
▿ _JSONKey(stringValue: "Index 0", intValue: 0)
- stringValue: "Index 0"
▿ intValue: Optional(0)
- some: 0
- CodingKeys(stringValue: "images", intValue: nil)
- CodingKeys(stringValue: "featured", intValue: nil)
- debugDescription: "Expected to decode String but found a number instead."
- underlyingError: nil
My JSON Decoder:
enum Result<Value> {
case success(Value)
case failure(Error)
}
func getItems(for userId: Int, completion: ((Result<Base>) -> Void)?) {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "api.jsonbin.io"
urlComponents.path = "/myurl"
let userIdItem = URLQueryItem(name: "userId", value: "\(userId)")
urlComponents.queryItems = [userIdItem]
guard let url = urlComponents.url else { fatalError("Could not create URL from components") }
var request = URLRequest(url: url)
request.httpMethod = "GET"
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = [
"secret-key": "xyz"
]
let session = URLSession(configuration: config)
let task = session.dataTask(with: request) { (responseData, response, responseError) in
DispatchQueue.main.async {
if let error = responseError {
completion?(.failure(error))
} else if let jsonDataTest = responseData {
// Now we have jsonData, Data representation of the JSON returned to us
// from our URLRequest...
// Create an instance of JSONDecoder to decode the JSON data to our
// Codable struct
let decoder = JSONDecoder()
do {
// We would use Post.self for JSON representing a single Post
// object, and [Post].self for JSON representing an array of
// Post objects
let posts = try decoder.decode(Base.self, from: jsonDataTest)
completion?(.success(posts))
} catch {
completion?(.failure(error))
}
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
completion?(.failure(error))
}
}
}
task.resume()
}
var base:Base?
func loadJson() {
getItems(for: 1) { (result) in
switch result {
case .success(let base):
self.base = base
dump(base)
case .failure(let error):
fatalError("error: \(error.localizedDescription)")
}
}
}
I'm new to swift and not sure what this Error is telling me or where the problem "decode String but found a number" is. I think there is something wrong with me struct.. I hope someone can help me there.
Please show the code where you want to parse the data to json.
let urlString = "your_url.json"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let data = data else { return }
do {
//Decode retrived data with JSONDecoder and assing type of Article object
let baseData = try JSONDecoder().decode(Base.self, from: data)
print(baseData) //whole project
print(baseData.status) //200.0
print(baseData.data.date)
for day in baseData.data.daily {
print(day.id)
print(day.images.icon)
print(day.images.featured)
print(day.images.gallery)
print(day.images.png)
print(day.name)
print(day.price)
print(day.priceIcon)
print(day.priceIconLink)
print(day.rarity)
print(day.readableType)
print(day.type)
}
for feature in baseData.data.featured {
print(feature.id)
print(feature.images.icon)
print(feature.images.featured)
print(feature.images.gallery)
print(feature.images.png)
print(feature.name)
print(feature.price)
print(feature.priceIcon)
print(feature.priceIconLink)
print(feature.rarity)
print(feature.readableType)
print(feature.type)
}
} catch let jsonError {
print(jsonError)
}
}.resume()
I tried this and it works for me.
By the way I was a little bit confused that Featured and Daily have all the same variables but are different models.
EDIT
Your posted data in the question are valid. The json from https://api.jsonbin.io/b/5acbd2dc214f9a2b84c6f167/1 is wrong or not consistent.
There is "featured": false in Daily and in Featured it is a string. In the struct is a string expected. So you will get a mismatch. Once you try to parse a string (works) and then you try to parse a boolean to a string (error).

Send JSON with Array and sub array of dictionary using swift and Alamofire

I want to make a post request with array of dictionary and also have sub array of dictionary, for example:
{
"Title": "You have a new gift from DevPro1034",
"StartDate": "2017-09-05 22:19:48",
"EndDate": "2017-09-07 22:19:48",
"ProviderId": "e134d34d-778c-4163-8935-a4844ea519fa",
"FeatureDetails": [
{
"CategoryId": 22,
"ProviderFeatureDetailId": 10588,
"CustomServices":
[
{
"ProviderCustomFeatureDetailId": 13247,
"InsiderPrice": 5.0
}
]
}
],
"CurrentDate": "2017-07-26T00:00:00",
"InsiderOfferSlots":
[
{
"AppointmentDate": "2017-09-05 22:19:48",
"StartTime": "2017-09-05T09:00:00"
}
],
"CampaignDetails": {
"ProviderId": "e134d34d-778c-4163-8935-a4844ea519fa",
"CampaignMessage": "Hi [First_Name],\nThis is DevPro1034. We have a few last minute offers. See availability.\n\nCampaignLink\n\nReply STOP to opt out",
"ScheduleDate": "2017-07-27T00:00:00",
"EmailTextContent": ""
}
}
here is My Code in which i am preparing a post request:
var featureDetailArray = [[String:AnyObject]]()
var customeServices = [[String:AnyObject]]()
for campaign in camUser.getAllCustomServices{
if campaign.insiderPrice != 0 {
let param = ["ProviderCustomFeatureDetailId" :campaign.providerCustomFeatureDetailId, "InsiderPrice": campaign.insiderPrice] as [String : Any]
customeServices.append(param as [String : AnyObject])
let parameter = ["CategoryId" :campaign.categoryId,
"ProviderFeatureDetailId": campaign.providerFeatureDetailId,
"CustomServices": customeServices
] as [String : Any]
featureDetailArray.append(parameter as [String : AnyObject])
}
}
// InsiderSlots
var appointmentArray = [[String:AnyObject]]()
for appintmentArray1 in camUser.startTimeDay1{
let parameter = ["StartTime" :appintmentArray1,
"AppointmentDate": camUser.appointmentDate1
//"ProviderUserId": AuthService.instance.userId
] as [String : Any]
appointmentArray.append(parameter as [String : AnyObject])
}
for appintmentArray2 in camUser.startTimeDay2{
let parameter = ["StartTime" :appintmentArray2,
"AppointmentDate": camUser.appointmentDate2
//"ProviderUserId": AuthService.instance.userId
] as [String : Any]
appointmentArray.append(parameter as [String : AnyObject])
}
for appintmentArray3 in camUser.startTimeDay3{
let parameter = ["StartTime" :appintmentArray3,
"AppointmentDate": camUser.appointmentDate3
//"ProviderUserId": AuthService.instance.userId
] as [String : Any]
appointmentArray.append(parameter as [String : AnyObject])
}
let campaignDetail = ["ProviderId": AuthService.instance.userId, "ScheduleDate":camUser.startDate,"CampaignMessage" : "Hi we are creating campaign","EmailTextContent": ""] as [String : Any]
let param : [String:Any] = [
"Title": "You have a new gift from DevPro1034" as AnyObject,
"StartDate": camUser.startDate as AnyObject,
"EndDate" : camUser.endDate as AnyObject,
"ProviderId": AuthService.instance.userId as AnyObject,
"FeatureDetails": featureDetailArray as AnyObject,
"InsiderOfferSlots" : appointmentArray as AnyObject,
"CampaignDetails": campaignDetail as AnyObject
]
let jsonData = try! JSONSerialization.data(withJSONObject: param, options: [])
print(jsonData)
let json = try! JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
print(json)
Alamofire.request(CREATE_CAMPAIGN, method: .post, parameters: param, encoding:JSONEncoding.default, headers: HEADER).responseJSON { (response) in
print(param)
I have seen a lot of questions and answers relevant to my Question but yet not found any solution, here is links whom I got initial help link One,
link Two

In Swift, how to convert a dictionary with any-type values to a JSON string

If a dictionary is [String:String], I know how to convert it into a JSON string.
However, I am wondering if I can convert following kind of dictionary into a JSON string? and how?
let parameters: [String:Any] = [
"Key" : "somekey",
"cid" : 23,
"timestamp" : 1732998762,
"number": 1124,
]
Try this code :
let parameters: [String:AnyObject] = [
"Key" : "somekey",
"cid" : 23,
"timestamp" : 1732998762,
"number": 1124,
]
do {
let theJSONData = try NSJSONSerialization.dataWithJSONObject(parameters, options: NSJSONWritingOptions(rawValue: 0))
let theJSONText = NSString(data: theJSONData,
encoding: NSASCIIStringEncoding)
print(theJSONText)
} catch {
}