How to get JSON Key and Values using Swift - arrays

I am trying to get below JSON result of Key and Value and store it into two separate arrays (keyArray and valuesArray). Keys I can append easily but values not appending. It's showing
error 'AnyObject' is not convertible to 'String'; did you mean to use 'as!' to force downcast?`.
JSON Keys are string but value is Int. How to append Int into string array?
{
"status_code": 200,
"message": “ranking”,
"result": {
"cost": 150,
"discount": 25,
“fixon": 0,
"fee": 0,
"check": 0,
"mailing": 20,
}
}
I tried
for (key, value) in results {
print("key (key) value2 (value)")
self.processtitle.append(key)
self.price.append(value) as! String? //'AnyObject' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
}

Dear you can't parse JSON by this way , so you can parse JSON by Decodable
But for pass this error you can add a condition:
if let key = key {
self.processtitle.append(key)
}
if let value = value {
self.price.append("\(value)")
}

Related

Transform JSON objects to an new array

How to transform JSON structure to an new array using Swift?
Initial JSON
{
"group1": {
"1/30/21": 100,
"1/31/21": 200
},
"group2": {
"1/30/21": 200,
"1/31/21": 300
},
"group3": {
"1/30/21": 300,
"1/31/21": 500
}
}
The array I'd like to convert would be like:
[
{
"group1": 100,
"group2": 200,
"group3": 300,
"date": "1/30/21",
},
{
"group1": 200,
"group2": 300,
"group3": 500,
"date": "1/31/21",
}
]
First use JSONSerialization to convert the json to a dictionary
let dictionary = try JSONSerialization.jsonObject(with: jsonIn.data(using: .utf8)!) as! [String: [String: Int]]
Then in two steps convert to the expected format by first creating a dictionary where the date is the key and groups and numbers (as a tuples) are the values
var temp = [String: [(String, Int)]]()
dictionary.forEach { key, value in
for (innerKey, innerValue) in value {
temp[innerKey, default: []].append((key, innerValue))
}
}
Then use this dictionary to create the array of dictionaries
let output = temp.map { (key, tuples) -> [String: Any] in
var result = [String: Any]()
for tuple in tuples {
result[tuple.0] = tuple.1
}
result["date"] = key
return result
}
and then back to json
let jsonOut = try JSONSerialization.data(withJSONObject: output)

How to parse JSON response which contains nested JSON array

I'm trying to parse a JSON response from an API and store the data to DATA CLASS and sending the data to recycler adapter as ArrayList.
The JSON Array has another array of objects inside, and I'm not able to find a way to properly parse that JSON response.
Here is my data class:
data class OrderDetails (
val orderId: String, // order_id value from json object goes here //
val restaurantName: String, // restaurant_name value from json object goes here //
val totalCost: String, // total_cost value from json object goes here //
val orderDate: String, // order_placed_at value from json object goes here //
val orderFoodDetails: String // food_items value in json response is an array and i'm stuck here //
)
Here is my Kotlin code:
try {
val data = it.getJSONObject("data")
val success = data.getBoolean("success")
if (success) {
val arrayData = data.getJSONArray("data")
for (i in 0 until arrayData.length()) {
val orderJsonObject = arrayData.getJSONObject(i)
val orderObject = OrderDetails(
orderJsonObject.getString("order_id"),
orderJsonObject.getString("restaurant_name"),
orderJsonObject.getString("total_cost"),
orderJsonObject.getString("order_placed_at"),
orderJsonObject.getJSONArray("food_items").toString() // getting array and storing as a string
)
orderList.add(orderObject)
for (orders in orderList) {
val foodData = orders.orderFoodDetails
val jsonFood = JSONArray(foodData)
for (j in 0 until jsonFood.length()) {
val foodJsonObject = jsonFood.getJSONObject(j)
val foodObject = OrderFoodDetails(
foodJsonObject.getString("food_item_id"),
foodJsonObject.getString("name"),
foodJsonObject.getString("cost")
)
ordersFood.add(foodObject)
}
}
}
Here is the Json response:
{
"data": {
"success": true,
"data": [
{
"order_id": "17790",
"restaurant_name": "Rotten Tomatoes",
"total_cost": "280",
"order_placed_at": "02-11-20 19:00:54",
"food_items": [
{
"food_item_id": "156",
"name": "Rotten Bhajiya",
"cost": "100"
},
{
"food_item_id": "155",
"name": "Rotten Salad",
"cost": "100"
},
{
"food_item_id": "154",
"name": "Rotten Soup",
"cost": "80"
}
]
},
Required Output
Prefered Output
My output
my current output
do you tried to use GSON or Moshy lib ?
This case will be easier solved with one of this :)
If you don't want to use one of them, just try to replace your for cycle to map or for each, to make it more readable. Looks like you make it right, but can you check the result of try catch block please?

Convert Json Object to Array format in Swift 4

I have the json
{
"message": null,
"data": {
"Commodity Department": {
"total": 2,
"completed": 1,
"completedWithDue": 0,
"completedWithOutDue": 1,
"inProgress": 1,
"inProgressWithDue": 0,
"inProgressWithOutDue": 1,
"statusCounter": null
}
}
I need to convert the each department json object to array. Currently each category value ("total": 0, "completed": 0, "completedWithDue": 0, "completedWithOutDue": 0, "inProgress": 0, "inProgressWithDue": 0, "inProgressWithOutDue": 0,) will be in object format. I need to convert in array and load to collectionview based on category. As of now I am trying to decode my json in the below code
public struct Dashboard: Decodable {
public let data : [String:Departments]
}
public struct Departments: Decodable {
public let total, completed, completedWithDue, completedWithOutDue: Int
public let inProgress, inProgressWithDue, inProgressWithOutDue: Int
}
let dashboard = try? JSONDecoder().decode(Dashboard.self, from: response.data!)
print(dashboard!.data.keys)
You can create an array of the values by adding a computed property to your struct
public struct Departments: Decodable {
public let total, completed, completedWithDue, completedWithOutDue: Int
public let inProgress, inProgressWithDue, inProgressWithOutDue: Int
var categoryValues: [Int] {get {
return [total, completed, completedWithDue, completedWithOutDue,
inProgress, inProgressWithDue, inProgressWithOutDue]
}
}
}
or create the array on the fly using map
dashboard?.data.mapValues{[$0.total, $0.completed, $0.completedWithDue, ...]}
You can decode json without knowing keys like this:
func printJSON(json: [String:Any]) {
let jsonKeys = json.keys //Gets the list of keys on the outer-most layer of the JSON
for i in 0..<jsonKeys.count {
let level1 = json[jsonKeys.index(jsonKeys.startIndex, offsetBy: i)] //retrieves the object with the specific keys
if let level2 = json[level1.key] as? [String:Any]{ //if the key is another object
printJSON(json: level2) //send it as a new json object to the function again
} else if let level2 = json[level1.key] as? [[String:Any]] { //if the key is an array of objects
for i in 0..<level2.count { //loop through the array
printJSON(json: level2[i]) //send each array element to the function
}
} else if let value = json[level1.key] as? String { //if value of String/Integer/Bool type
print(value) //then only print values of the specified type (String-type in this case)
}
}
}
See full article Here

How to retrieve value from all keys with the same name from an array of dictionaries

I would like to retrieve the values from keys named "termKey" from all dictionaries in an array of dictionaries (as I want to display the values in a UITableView). Any suggestions?
Here's the array of dictionaries:
{
"questionData": [
{
"termKey": "respiration"
},
{
"termKey": "mammals"
}
]
}
This is the flattened array:
[(key: "termKey", value: "respiration"), (key: "termKey", value: "mammals")]
The output I want would be something like: ["respiration", "mammals"]
let array = [(key: "termKey", value: "respiration"), (key: "termKey", value: "mammals")]
array.map({ $0.value })
And you will get an array of the values that looks like:
["respiration", "mammals"]
Use compactMap on the array and lookup the dictionary key in the closure:
let questionData = [["termKey": "respiration"], ["termKey": "mammals"], ["badKey": "foo"]]
let values = questionData.compactMap { $0["termKey"] }
print(values)
["respiration", "mammals"]
compactMap runs its closure for each element in the array to create a new array. Here, we look up the value for the key "termKey". Dictionary lookups return an optional value. If the key is not present, the result will be nil. compactMap skips the nil values and unwraps the values that are present.
Decode the JSON into structs and map the result to the termKey values of questionData.
struct Response: Decodable {
let questionData : [Question]
}
struct Question: Decodable {
let termKey : String
}
let jsonString = """
{"questionData": [{"termKey": "respiration"},{"termKey": "mammals"}]}
"""
let data = Data(jsonString.utf8)
do {
let result = try JSONDecoder().decode(Response.self, from: data)
let termKeys = result.questionData.map{$0.termKey}
} catch { print(error) }

Converting and Passing in an Array of Numbers Using MongoDB `$in` Operator

In my MongoDB/Node backend I am taking in passed-in parameters and then filtering on some data.
The first thing I do is take in string values (that happen to represent numbers) such as "1", "2", etc. and turn them into a comma-separated array.
Now I need to filter on a property called "responsibilitySequence". The thing is, the values for this property are of type "number", not "string".
So how do I adjust the following function so that what gets passed-in as an array that Mongo will evaluate using the $in operator, consists of numbers, not string values?
if (responsibilitySequence) {
let arrResponsibilitySequence = [];
arrResponsibilitySequence = responsibilitySequence.split(",");
_.each(arrResponsibilitySequence, (l, key, c) => {
arrResponsibilitySequence[key] = new RegExp(arrResponsibilitySequence[key], "i");
});
search.responsibilitySequence = {
$in: arrResponsibilitySequence
};
}
You could just map the values and parse them as int:
if (responsibilitySequence) {
let arrResponsibilitySequence = responsibilitySequence.split(",");
search.responsibilitySequence = {
$in: arrResponsibilitySequence.map(x => Number.parseInt(x)) // or just +x
};
}

Resources