swiftui

Creating an array of Int in JSON


I need to put an array of 'Tag' ids into a json.

import Foundation
import SwiftData

@Model
final class Tag {
    
    var id = -1
    
    var name = ""
 
    var desc = ""
    
    @Relationship(inverse:\Event.tags) var events: [Event]?
    
    init(id: Int, name: String, desc: String){
        self.id = id
        self.name = name
        self.desc = desc
    }
    
}

I create the Json with:

var eventObject: [String: Any] = [:]

I tried to do it this way:

if let itemTags: [Tag] = item.tags {
    if !itemTags.isEmpty {
        eventObject["tags"] = "[\(itemTags.map{String($0.id)}.joined(separator: ","))]"
    }
}

but that results in a string containing

"tags" : "[2,6]"

I also tried to iterate over it, but I get an error

if let itemTags: [Tag] = item.tags {
    if !itemTags.isEmpty {
        var tagMap = [Int]()
        ForEach(itemTags.indices, id: \.self) { index in
            tagMap.append(itemTags[index].id)
        }
        eventObject["tags"] = tagMap
    }
}

Ambiguous use of 'init(_:id:content:)'

I don't understand why, as I can use ForEach on that array in Views.

What is the best way to end up with:

"tags" : [2,6]


Solution

  • ForEach is a View that should return another View. To iterate over your itemTags array and append, use a normal loop, such as: for index in itemTags.indices { tagMap.append(itemTags[index].id) }. Or itemTags.forEach{ tagMap.append($0.id) }.

    Example code using your original setup:

     if let itemTags: [Tag] = item.tags {
         if !itemTags.isEmpty {
             var tagMap = [Int]()
             itemTags.forEach { tagMap.append($0.id) } // <--- here
             eventObject["tags"] = tagMap
         }
     }
    

    Or simply:

     eventObject["tags"] = item.tags.map{$0.id}
    

    Note, @Model class... already conform to Identifiable, there is no need for yet another var id.

    To get a JSON string from your eventObject suitable for a POST request for example, try this:

    print("---> eventObject: \(eventObject)")
    
         do {
             let data = try JSONSerialization.data(withJSONObject: eventObject, options: [])
             
             // display the resulting json string for testing
             let jsonString = String(data: data, encoding: .utf8)!
             print("---> jsonString: \(jsonString as AnyObject) \n")
           
             // add to the request
             request.httpBody = try JSONEncoder().encode(data)
             // .....
         } catch{
             print(error)
         }