SwiftUI List from JSON/Dictionary - json

Just starting out with SwiftUI so apologies for the basic question. I have a dictionary created from a JSON file of the following format:
{
{
"first_name": "John",
"last_name": "Doe",
"email": "John.doe#domain.com"
},
{
"first_name": "Jane",
"last_name": "Doe",
"email": "Jane.doe#domain.com"
}
}
I would like to create a list of first_name that I can then use in other files, the names are unique so there shouldn't be any need for UUID. So far I can load my data into a swift file and display it with the use of:
struct DataTest: View {
let people = Bundle.main.decode("people.json")
var body: some View {
VStack{
ForEach(0 ..< people.count){number in
Text("\(people[number].first_name)")
}
}
}
}
Is there any way that I can generate an array or list without the use of a ForEach loop? I tied something like #State private var = people.first_name, but that did not seem to work.

Assuming that the is this structure:
struct Person {
var first_name : String
var last_name : String
var email: String
}
and people is [Person], you can map a single property like this:
let firstNamesOnly = people.map { $0.first_name }
or, newly in Swift 5.2:
let firstNamesOnly = people.map(\.first_name)
You could use this in a computed property and List by doing:
var firstNames : [String] {
people.map(\.first_name)
}
var body: some View {
VStack{
ForEach(firstNames, id: \.self) { firstName in
Text(firstName)
}
}
}

Related

Parse json in Kotlin

I have json like:
{
"member": [
{
"name": "string",
"lastname": "string",
"email": "string",
"address": {
"city": "string",
"country": "string"
}
}
]
}
I parse with the fromGson(google)
Gson().fromJson(jsonString,Member::class.java)
I already have a class to map this json on each field
data class Member(
var name: String,
var lastname: String,
var email: String,
var address: HashMap<String, String>
)
but I have problem to map address, I don't know why
it's only work when json like
"address":
{
"city": "string"
}
it look like I need parse map on json object whos in json object too
array of hashmap didn't work also
Probably you need a wrapper class on the top of member class, try this:
private val jsonString =
"{\"member\": [{ \"name\": \"string\",\"lastname\": \"string\",\"email\": \"string\",\"address\": { \"city\": \"string\",\"country\": \"string\" } }]}"
data class Member(
var name: String,
var lastname: String,
var email: String,
var address: HashMap<String, String>
)
class Response(val member: List<Member>)
fun parse() {
val response = Gson().fromJson(jsonString, Response::class.java)
for (member in response.member){
// do something
}
}

How to create a Swift model for JSON

{"dataList":{"1547795650562": {
"c0a8007b-6759-111d-8167-59e8dabe0086": {
"recordDate": 1547795650562,
"resultValue": "160",
"vitalParameter": {
"uom": {
"code": "KG",
"name": "KG",
"id": "c0a8007b-6759-111d-8167-59e76204007f"
},
"resultType": {
"code": "VSRTNUMERIC",
"name": "Numeric",
"id": "20cf4756-40b0-4cc1-acb5-861765370a41"
},
"code": "29463-7",
"name": "Weight",
"id": "c0a8007b-6759-111d-8167-59e8dabe0086"
},
"id": "c0a8007b-6855-1d16-8168-5fd18fa301b7"
}}
}}
getting 1547795650562 and c0a8007b-6759-111d-8167-59e8dabe0086 as class names. But I dont want like this;
class DataList : NSObject, NSCoding{
var 1547795650562 : 1547795650562!
}
class 1547795650562 : NSObject, NSCoding{
var c0a8007b6759111d816759e8dabe0086 : VitalParameter!
}
But the problem here is, 1547795650562 and c0a8007b-6759-111d-8167-59e8dabe0086 cannot be hard coded because they may change.
c0a8007b-6759-111d-8167-59e8dabe0086 is dynamic id and 1547795650562 is recordDate. Inner object is repetitive.
But I have to map as the keys are of recordDate and id respectively.
Try using Codable instead of NSCoding to parse your JSON data.
Models:
struct Root: Codable {
let dataList: [String:[String:Record]]
}
struct Record: Codable {
let recordDate: Int
let resultValue: String
let vitalParameter: VitalParameter
let id: String
}
struct VitalParameter: Codable {
let uom, resultType: ResultType
let code, name, id: String
}
struct ResultType: Codable {
let code, name, id: String
}
Parse the JSON data using above models like,
do {
let response = try JSONDecoder().decode(Root.self, from: data)
print(response)
} catch {
print(error)
}
Note: You can use https://app.quicktype.io to get the models from your JSON instantly. Make the changes as per your requirement and you're good to go.

Casting dictionary of sets to JSON Object

I'm trying to build request body like this form:
{
"user": {
"id": 1,
"id": 2,
"id": 4
}
}
My first idea was built json from string and cast it to dictionary String and Any, but this solution have a issue. Some "id" are missing on casting by JSONSerialization step.
I tried to use:
var dictionary: [String : Any] = ["name" : "John"]()
var selectedIDs = Set<NSDictionary>()
// Adding values to selectedIDs set
let userIDDict = ["id" : id] as NSDictionary
selectedIDs.insert(userIDDict)
dictionary.updateValue(selectedIDs, forKey: "user")
But it cannot be cast by JSONSerialization (Invalid type in JSON write).
How can i resolve problem, which i'm facing?
Creating this request is not a problem; it's just not proper JSON, so you shouldn't try to use JSONSerialization. It's just a string, and so you can create that string:
let idKeyValues = ids.map { "\"id\": \($0)" }.joined(separator: ",\n ")
let request = """
{
"user": {
\(idKeyValues)
}
}
"""
===>
{
"user": {
"id": 1,
"id": 2,
"id": 4
}
}
The proper way to express this in JSON would be:
{
"user": {
"ids": [1, 2, 4]
}
}
With that, a Codable implementation should be very straightforward.

Swift how to express JSON in structs

I want to express the following JSON and convert to swift structs
1) I get error in the third line full_plan "comma is missing". I don't know why a comma is required? I need help fixing it
2) If that is fixed will the structs shown below is accurate to convert to JSON?
Please note: add_ons may be missing in the JSON for some plans, so second plan shown does not have add_ons.
Basically I am asking help to fix the JSON and the struct for swift.
{
"id": "100",
"plans":
[
"full_plan":
{
"plan":
[
{ "plan_type": "Legacy" },
{ "contract_duration_months": "12" }
],
"add_ons" :
[
{ "parking": "yes"},
{ "washerDryer": "no" }
]
},
"full_plan":
{
"plan":
[
{ "plan_type": "New" },
{ "contract_duration_months": "0" }
]
}
]
}
struct TopPlan : Decodable {
var uniqueId: String?
var Plans: [FullPlan]?
enum CodingKeys : String, CodingKey {
case uniqueId = "id"
case Plans = "plans"
}
}
struct FullPlan: Decodable {
var Plan: PlanJSON?
var freePlan: AddOnsJSON?
enum CodingKeys : String, CodingKey {
case pricedPlan = "plan"
case freePlan = "add_ons"
}
}
struct PlanJSON: Decodable {
var planType: String?
var duration: String?
enum CodingKeys : String, CodingKey {
case planType = "plan_type"
case duration = "contract_duration_months"
}
}
struct AddOnsJSON: Decodable {
var parking: String?
var washerDryer: String?
enum CodingKeys : String, CodingKey {
case parking = "parking"
case washerDryer = "washerDryer"
}
}
Short answer: your current JSON is invalid syntax.
You are using "full_plan" as a key (which would be fine if "plans" was an object) inside an array. Arrays in JavaScript (and thus in JSON) are unkeyed. You should either remove "full_plan" and just use the object that it refers to like "plans": [{}, {}, etc], or if you need to keep the object key wrap the entire item in curly braces such as "plans": [{ "full_plan": {}}, { "full_plan": {}}, etc]
You should build this up from the bottom (and if you post your question in a form that is executable in a Playground you will get answers faster). As it stands your plan JSON is unfortunate. Your struct states that you want a hash and you provide it with an array of hashes (which should be merged to get what you want). Try it like this:
import Cocoa
let jsonData = """
{ "plan_type": "Legacy",
"contract_duration_months": "12"
}
""".data(using: .utf8)!
struct PlanJSON: Decodable {
var planType: String?
var duration: String?
enum CodingKeys : String, CodingKey {
case planType = "plan_type"
case duration = "contract_duration_months"
}
}
do {
let plan = try JSONDecoder().decode(PlanJSON.self, from: jsonData)
print(plan)
} catch {
print(error)
}
That way you will be given enough information to further fix your JSON, but the rest looks ok.

Creating Model using Swifty JSon Model

[
{
"_id": "1212323",
"row": 1,
"column": 1,
"displayType": 0,
"item": {
"type": "category_",
"data": {
"_id": "595a1446cb91951900b0b4b0",
"title": "something",
"fullImage": "http://assets.something.mobi/curated/something (2).jpg",
"halfImage": "http://assets.something.mobi/curated/something (1).jpg"
}
}
},
{
"_id": "595a148ccb91951900b0b4b5",
"row": 2,
"column": 1,
"displayType": 1,
"item": {
"type": "curatedlist",
"data": {
"_id": "595b34abcb9195190c0ae378",
"active": "true",
"title": "sample something list",
"fullImage": "http://assets.something.mobi/curated/something (2).jpg",
"halfImage": "http://assets.something.mobi/curated/something (2).jpg"
}
}
}
]
very new to SwiftyJSON and Alamofire some one please help me to create a model for it im able get JSON responce using almofire but not able to create a proper swifty json model for this
I have done this using two separate model classes, one to directly map all the values and other used to fetch directly as an array from it.
For some who just starting or stuck with creating model and mapping values can try these or someone is an expert can suggest a better solution to improve the implementation
1.CategoryModel: NSObject
import UIKit
import SwiftyJSON
class CategoryModel: NSObject {
var resultArray : NSArray!
var _id : String!
var row : NSInteger!
var column : NSInteger!
var displayType : NSInteger!
var type : String?
var _id1 : String?
var title : String?
var fullImage : String?
var halfImage : String?
// var item
required init(JsonDashBoard: JSON) {
_id = JsonDashBoard["_id"].stringValue
row = JsonDashBoard["row"].intValue
column = JsonDashBoard["column"].intValue
displayType = JsonDashBoard["displayType"].intValue
//MARK:- Inside Item Dictionary
type = JsonDashBoard["item"]["type"].stringValue
//MARK:- Inside Item/dataDictionary
_id1 = JsonDashBoard["item"]["data"]["_id"].stringValue
title = JsonDashBoard["item"]["data"]["title"].stringValue
fullImage = JsonDashBoard["item"]["data"]["fullWidthImage"].stringValue
halfImage = JsonDashBoard["item"]["data"]["halfWidthImage"].stringValue
}
}
2.CategoryListModel:NSObject
import UIKit
class CategoryListModel: NSObject {
var items : NSArray? = nil;
required init(_items: NSMutableArray) {
self.items = _items
}
}
and using these model classes you can map values using the below code snipet
manager.request(routeUrl, method: .get).responseJSON { (responseObject) -> Void in
if responseObject.result.isSuccess {
let resJson = JSON(responseObject.result.value!)
let categoryList = NSMutableArray()
for (_,subJson):(String, JSON) in resJson {
let model = CategoryModel(JsonDashBoard: subJson)
categoryList.add(model)
//Do something you want
print(subJson)
}
let categoryListModel = CategoryListModel(_items: categoryList)
success(categoryListModel)
}
if responseObject.result.isFailure {
let error : Error = responseObject.result.error!
failure(error)
}
}