Related
I'm suffering for a week, you are my last hope, here is the JSON that I'm trying to parse, it comes from the server
[
1,
null,
[
{
“categories” : [
{
“id” : 26,
“category” : “sweaters”
}
],
“sellingPrice” : “6000.00",
“statusSite” : “a”,
“type” : “wear”,
“id” : 30024,
“payoutType” : “3”,
“style” : “Avant Garde”,
“count” : 1,
“status” : “active”,
“images” : [
{
“productId” : 30024,
“image” : “2000000211176-066e7e39b0a590501fe85155a571258e.jpg”,
“imageMin” : “2000000211176-a7e0626b3512f517f23b1e091224e759.jpg”,
“name” : “6.jpg”
},
{
“productId” : 30024,
“image” : “2000000211176-25bc8175742d959448f0c8211d7753f6.jpg”,
“imageMin” : “2000000211176-6212cd8a58a4e7269d282651eb316429.jpg”,
“name” : “3.jpg”
},
{
“productId” : 30024,
“image” : “2000000211176-3bd4648416c5a1e525417673a0328060.jpg”,
“imageMin” : “2000000211176-e3bf05a38f430013e9077637244e45b8.jpg”,
“name” : “1.jpg”
},
{
“productId” : 30024,
“image” : “2000000211176-561ce49fbb4de29b8ef905f66279f432.jpg”,
“imageMin” : “2000000211176-67f41b0a32e48a380d5b5d27c7dcaea8.jpg”,
“name” : “4.jpg”
},
{
“productId” : 30024,
“image” : “2000000211176-c37ff0bd838d2f8eaabaa09e45a8b07f.jpg”,
“imageMin” : “2000000211176-b6e96c3ff88965f301ade7257eb8653e.jpg”,
“name” : “2.jpg”
},
{
“productId” : 30024,
“image” : “2000000211176-f3c14b80583e079d11b9fc5556af5f8b.jpg”,
“imageMin” : “2000000211176-4907e8502f739b56579f53a5eaa8d0a9.jpg”,
“name” : “5.jpg”
}
],
“priceInAct” : null,
“additionallyHeldAmounts” : null,
“vendorCode” : “000000238”,
“amountOfCommission” : null,
“searchWords” : “10sei0otto, ,dieciseizerotto,sweater ,Свитер ,Gently used,Отличное,Black,Черный,,“,
“id1c” : “2000000211176",
“brand” : {
“name” : “10sei0otto”,
“id” : 987
},
“saleStatus” : “A”,
“tradeIn” : “N”,
“composition” : null,
“isHidden” : false,
“created” : “2022-12-11T00:00:00.000Z”,
“collections” : [
],
“name” : “Black Leather Patched Sweater”,
“userId” : 2312,
“sex” : “M”,
“imagesPath” : “[\“2000000211176_1.jpg\“,\“2000000211176_2.jpg\“,\“2000000211176_3.jpg\“,\“2000000211176_4.jpg\“,\“2000000211176_5.jpg\“,\“2000000211176_6.jpg\“]”,
“badgeSale” : 0,
“badge” : “{\“background\“:\“#FF00FF\“,\“image\“:\“https:\/\/toppng.com\/uploads\/preview\/sale-badge-sale-tag-symbol-11563037290rmf7mns4rx.png\“,\“text\“:\“\”}“,
“features” : [
],
“timestampPrice” : null,
“condition” : “Gently used”,
“place” : 1,
“saleDate” : null,
“languages” : [
{
“description” : “”,
“discount” : “0.00”,
“languageCode” : “en-EN”,
“size” : “XL”,
“price” : “170.00”
},
{
“description” : “”,
“discount” : “0.00”,
“languageCode” : “ru-RU”,
“size” : “XL”,
“price” : “11000.00”
}
],
“userId1c” : “000000238”
}
]
]
import Alamofire
import SwiftyJSON
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var jsonResultsTextView: UITextView!
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var buttonLbl: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
buttonLbl.setTitle("PUSH", for: .normal)
}
#IBAction func buttonAction(_ sender: Any) {
AF.request("https://beta.server.spin4spin.com/auth/login", method: .post, parameters: login, encoding: JSONEncoding.default).response { response in
print(response)
}
}
#IBAction func get(_ sender: Any) {
if let urlString = URL(string: "https://beta.server.spin4spin.com/admin/raw-catalog?search=2000000211176") {
URLSession.shared.dataTask(with: urlString) { data, response, error in
if let data = data {
print(data)
do {
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
print(responseJSON as Any)
let decoder = JSONDecoder()
let json = try? decoder.decode([[Dats]].self, from: data)
print(json as Any)
} catch let error {
print(error)
}
}
}.resume()
}
}
}
struct Dats: Codable
{
let integer: Int
let null: String?
struct ResponseClass: Codable
{
struct FinalClassArray: Codable
{
let sellingPrice, statusSite, type: String
let id: Int
let payoutType, style: String
let count: Int
let status: String
let vendorCode: String
let searchWords, id1C: String
let saleStatus, tradeIn: String
let isHidden: Bool
let created: String
let name: String
let userID: Int
let sex, imagesPath: String
let badgeSale: Int
let badge: String
let condition: String
let place: Int
let userId1C: String
}
}
}
It throws a Nil error when trying to decode the values
enter image description here
Tried using Alamofire, SwiftyJson nothing helps to avoid errors
The main problem is that the root object is a heterogenous array, which cannot be decoded synthesized. This is very unusual and cumbersome.
You have to implement init(from decoder: and decode each item in the array manually. I'm talking about Decodable, SwiftyJSON has become obsolete.
And there are three properties which don't match the keys, id1c, userId and userId1c (note the different lowercase and uppercase characters)
These structs match the given JSON
struct Dats: Decodable
{
let integer: Int
let null: String?
let items : [FinalClassArray]
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
self.integer = try arrayContainer.decode(Int.self)
self.null = try arrayContainer.decodeIfPresent(String.self)
self.items = try arrayContainer.decode([FinalClassArray].self)
}
}
struct FinalClassArray: Decodable
{
let sellingPrice, statusSite, type: String
let id: Int
let payoutType, style: String
let count: Int
let status: String
let vendorCode: String
let searchWords, id1c: String
let saleStatus, tradeIn: String
let isHidden: Bool
let created: String
let name: String
let userId: Int
let sex, imagesPath: String
let badgeSale: Int
let badge: String
let condition: String
let place: Int
let userId1c: String
}
And this is the code to decode the data (I renamed the function get as loadData)
#IBAction func loadData(_ sender: Any) {
guard let url = URL(string: "https://beta.server.spin4spin.com/admin/raw-catalog?search=2000000211176") else { return }
URLSession.shared.dataTask(with: url) { data, _, error in
if let error { print(error); return }
do {
let json = try JSONDecoder().decode(Dats.self, from: data!)
print(json)
} catch {
print(error)
}
}.resume()
}
Please help make this work I've been trying to figure out JSON and Swift for a week and facing this problem for 5 hours so far today.
Error Received
ERROR WHEN DECODING JSON keyNotFound(CodingKeys(stringValue: "MP", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "MP", intValue: nil) ("MP").", underlyingError: nil))
YEAR IS NIL
Code
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: "newLogData", ofType: "json") else { return }
guard let jsonString = try? String(contentsOf: URL(fileURLWithPath: jsonURL), encoding: String.Encoding.utf8) else { return }
// print(jsonString)
// Print Info for TESTING
var year: UserDay?
do {
year = try JSONDecoder().decode(UserDay.self, from: Data(jsonString.utf8))
} catch {
print("ERROR WHEN DECODING JSON \(error)")
}
guard let results = year else {
print("YEAR IS NIL")
return
}
print(results)
}
}
JSON
{
"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]}]
}
}
First, replace let WP: UserWP with an array:
struct UserDay: Codable {
let MP: UserMP
let WP: [WPData]
}
Then decode [String:UserDay] instead of UserDay:
try JSONDecoder().decode([String:UserDay].self, from: Data(jsonString.utf8))
Note that this will return a dict with key-value pairs "01/01/2020":UserDay object.
This means you can't assign a dictionary [String: UserDay] to a UserDay variable. Instead you can access the dict by a key which is some date (eg. "01/01/2020") and then assign it to your UserDay variable:
let result = try JSONDecoder().decode([String:UserDay].self, from: Data(jsonString.utf8))
let someYear = result["01/01/2020"]
Note that someYear will be optional so you may want to provide a default value or force-unwrap it.
I am a beginner programmer and I couldn't parse my json file. I can see datas in my console but I need help to parse json datas. I shared my json datas from url and I would like to parse with Alamofire. I installed PodFile with Alamofite and SwiftyJSON. I don't have any error but I need help for parse it.
Also I created string Arrays for following datas. I will append data in arrays.
[
{
"id" : 1,
"team" : "Liverpool",
"players" : [
{
"id" : 2,
"name" : "Alisson",
"position" : "Goal Keeper",
"number" : "13"
},
{
"id" : 3,
"name" : "Salah",
"position" : "Forward",
"number" : "10"
}
],
"trophies" : [
"2019 champions league",
"2005 champions league"
],
"logoUrl" : "url"
},
{
"id" : 4,
"team" : "Real Madrid",
"players" : [
{
"id" : 5,
"name" : "Ramos",
"position" : "Defender",
"number" : "4"
},
{
"id" : 6,
"name" : "Benzema",
"position" : "Forward",
"number" : "9"
}
],
"trophies" : [
"2018 champions league",
"2017 champions league",
"2016 champions league"
],
"logoUrl" : "url"
}
]
import Alamofire
import SwiftyJSON
func fetchJsonData(){
DispatchQueue.main.async {
Alamofire.request(url).responseData { response in
guard let data = response.data else { return }
do {
let res = try JSONDecoder().decode([PageData].self, from:data)
print(res)
} catch {
print("having trouble converting it to a dictionary" , error)
}
}
}
}
// this is my modal file
struct PageData: Codable {
let team: String
let players: [Player]
let trophies: [String]
let logoUrlL: String
}
struct Player: Codable {
let id: Int
let name,position, number: String?
}
You need responseData for using JSONDecoder
Alamofire.request(url).responseData { response in
guard let data = response.data else { return }
do {
let res = try JSONDecoder().decode([PageData].self, from:data)
print(res)
} catch {
print("having trouble converting it to a dictionary" , error)
}
}
Also players and trophies are arrays
struct PageData: Codable {
let team: String
let players: [Player]
let trophies: [String]
let logoUrlL: String
}
struct Player: Codable {
let id: Int
let name,position, number, type, quantity: String?
}
I'm using Alamofire and SwiftyJSON and I want to check if the response contains a value that I will type in a search bar.
I've just got the whole JSON file of 1666 objects and append it into my objects array and then I'm searching for value, but it takes too long.
func parseJSON(json: JSON, parse: ParseType) {
var i = 0
var j = 0
switch parse {
case .group:
for elements in json["groups"] {
if let groupId = json["groups"][i]["id"].int {
let groupName = json["groups"][i]["name"].string
// print(groupId)
let group = Groups(id: groupId, name: groupName!)
groupsArray.append(group)
i += 1
} else {
print("Error can't parse JSON")
}
}
func getGroupsData(url: String, groupName: String) {
Alamofire.request(url, method: .get).responseJSON { (response) in
if response.result.isSuccess {
print("Is Success")
let json = JSON(response.result.value)
self.parseJSON(json: json, parse: .group)
if let group = self.groupsArray.first(where: {$0.name == groupName}) {
print("found \(group)")
let searchScheduleUrl = url + "\(group.id)"
self.getGroupSchedule(url: searchScheduleUrl)
} else {
print("Can't find group")
}
} else {
print(response.result.error)
}
}
}
And here is JSON:
{
"groups" : [
{
"faculty" : {
"id" : 101,
"abbr" : "ИнГО",
"name" : "Гуманитарный институт"
},
"id" : 26262,
"spec" : "47.06.01 Философия, этика и религиоведение",
"kind" : 3,
"level" : 3,
"name" : "33865\/4702",
"type" : "common"
},
{
"faculty" : {
"id" : 95,
"abbr" : "ИКНТ",
"name" : "Институт компьютерных наук и технологий"
},
"id" : 27432,
"spec" : "09.03.04 Программная инженерия",
"kind" : 0,
"level" : 1,
"name" : "в13534\/22",
"type" : "evening"
},
{
"faculty" : {
"id" : 92,
"abbr" : "ИСИ",
"name" : "Инженерно-строительный институт"
},
"id" : 26322,
"spec" : "08.06.01 Техника и технологии строительства",
"kind" : 3,
"level" : 1,
"name" : "13163\/0801",
"type" : "common"
}, and so on...
I want to check for example:
if name: "13541/1" is in dictionary and if it is i want to get it's id
You can try
struct Root: Codable {
let groups: [Group]
}
struct Group: Codable {
let faculty: Faculty
let id: Int
let spec: String
let kind, level: Int
let name, type: String
}
struct Faculty: Codable {
let id: Int
let abbr, name: String
}
do {
let res = try JSONDecoder().decode(Root.self,from:data)
if let item = res.groups.first(where:{ $0.name == YourName }) {
print(item.id)
}
}
catch {
print(error)
}
{
"uri" : "http://www.edamam.com/ontologies/edamam.owl#recipe_f9e656dd9d2b4db9816340687d01722c",
"calories" : 38,
"totalWeight" : 113.25,
"dietLabels" : [ "LOW_FAT" ],
"healthLabels" : [ "SUGAR_CONSCIOUS", "VEGAN", "VEGETARIAN", "PEANUT_FREE", "TREE_NUT_FREE", "ALCOHOL_FREE" ],
"cautions" : [ ],
"totalNutrients" : {
"ENERC_KCAL" : {
"label" : "Energy",
"quantity" : 38.505,
"unit" : "kcal"
},
"FAT" : {
"label" : "Fat",
"quantity" : 0.41902500000000004,
"unit" : "g"
},
"FASAT" : {
"label" : "Saturated",
"quantity" : 0.044167500000000005,
"unit" : "g"
},
"FAMS" : {
"label" : "Monounsaturated",
"quantity" : 0.0124575,
"unit" : "g"
},
"FAPU" : {
"label" : "Polyunsaturated",
"quantity" : 0.043035000000000004,
"unit" : "g"
}
}
}
/*
* networking method
*/
func getNutritionData(url: String) {
Alamofire.request(url, method: .get)
.responseString { response in
if response.result.isSuccess {
print("Sucess! Got the Nutrition data")
let nutritionJSON : JSON = JSON(response.result.value!)
//print(nutritionJSON)
self.updateNutritionData(json: nutritionJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.caloriesLable.text = "Connection Issues"
}
}
}
func updateNutritionData(json: JSON) {
let calories = json["calories"].intValue
print(calories)
}
^ When I try to get the calories for example, I get nil
In the nutritionData method I tried using .responseJSON but it was throwing an error so I switched to .responseString. I want to get the "totalNutrients" information from that JSON. Help would be appreciated
It's better to use method with responseJSON instead of responseString
Alamofire.request(url, method: .get, parameters:nil, encoding: JSONEncoding.default).responseJSON { response in
print(response)
if let json = response.result.value as? [String:Any] {
print(json["calories"])
}
}
and then try
Ary alamofire.response, and then directly parse data in to JSON
Alamofire.request(url, method: .get).response { response in
if response.result.isSuccess {
let nutritionJSON : JSON = JSON(response.data)
self.updateNutritionData(json: nutritionJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.caloriesLable.text = "Connection Issues"
}
}
func updateNutritionData(json: JSON) {
let calories = json["calories"].intValue
print(calories)
}
You should definitely be using responseJSON() if you just wanna serialize JSON. If you're trying to use it with a Decodable object, you should be using responseData() and decoding one of your custom types with the data. Always validate.
func getNutritionData(url: String) {
Alamofire.request(url)
.validate(statusCode: 200...200)
.validate(contentType: ["application/json"])
.responseJSON { (response) in
switch response.result {
case .success(let json):
// Do something with the json.
let dict = json as? [String: Any]
print(dict["<KEY>"]!)
case .failure(let error):
print(error)
}
}
}