0

I'm new in swift. I'm trying to add an Array to a specific key in my Dictionary.

I have the following code:

var myArray : Array<Links> = []
var myDict : Dictionary<String, AnyObject> = [:]

myDict["links"] = myArray as AnyObject?  // I need help in this row, It does not work.

This is the Json structure I have in myDict and I'm trying to set:

id : "blabla"
links: [
   0: {key1: "a", key2: "b", name: "c", link: "d"}
   1: {key1: "e", key2: "f", name: "j", link: "h"}
]

Please, consider I already have all the rest working properly. My only problem is how to add my array in the dictionary as commented in the code above.

My JSON structure:

enter image description here

I hope I could make myself clear enough. Thank you.

1
  • What do you mean by "It does not work"? What's Links? Commented Dec 30, 2016 at 19:03

3 Answers 3

2

First of all don't cast types up and don't annotate types unless the compiler complains.

Second of all a JSON dictionary is [String:Any] in Swift 3.

Further the recommended syntax to create an empty collection object is

var myDict = Dictionary<String, Any>()

Assuming your array – actually a dictionary – is

let myArray = [
    0: ["key1": "a", "key2": "b", "name": "c", "link": "d"],
    1: ["key1": "e", "key2": "f", "name": "j", "link": "h"]
]

just assign it:

myDict["links"] = myArray

Even if there is a struct

struct Link {
    var key1, key2, name, link : String
}

and the array dictionary is

let linkDictionary = [
    0: Link(key1:"a", key2: "b", name: "c", link: "d"),
    1: Link(key1:"e", key2: "f", name: "g", link: "h")]

you can assign it if the value type is Any

myDict["links"] = linkDictionary
Sign up to request clarification or add additional context in comments.

6 Comments

I'd say var myDict = [String : Any]() is more idiomatic Swift.
@Hamish Indeed it is but for a beginner the subtle difference between [] and [:] might be more confusing than concrete Array<... and Dictionary<...
Hi, thank you for you answer but you did exactly what I did. The only change was in the cast. If I do not add a 'AnyObject' in this row myDict["links"] = myArray as AnyObject? I got a compiler error saying 'Cannot assign value of type Array<Link> to AnyObject'. I just added a print console, this is how my json is coming: id = "blala"; links = ( "MyProject.Link", "MyProject.Link", "MyProject.Link", );
Then there is something wrong with your Links struct (the name should be singular) or with other wrong type annotations. Do not use AnyObject in Swift 3. I updated the answer.
Actually 'Link' is a class. Could it be the problem?
|
0

Assuming, for a second, that links really was an array, it would be:

var dictionary: [String: Any] = [
    "id": "blabla",
    "links": [
        ["key1": "a", "key2": "b", "name": "c", "link": "d"],
        ["key1": "e", "key2": "f", "name": "j", "link": "h"]
    ]
]

// retrieve links, or initialize it if not found

var links = dictionary["links"] as? [[String: String]] ?? [[String: String]]()

// add your new link to local dictionary

links.append(["key1": "k", "key2": "l", "name": "m", "link": "n"])

// update original structure

dictionary["links"] = links

Personally, though, when I see a repeating dictionary structure like your links, this screams for a real model for these objects. For example:

struct Foo {
    let id: String
    var links: [Link]?
}

struct Link {
    let key1: String
    let key2: String
    let name: String
    let link: String
}

var foo = Foo(id: "blabla", links: [
    Link(key1: "a", key2: "b", name: "c", link: "d"),
    Link(key1: "e", key2: "f", name: "j", link: "h") 
])

foo.links?.append(Link(key1: "k", key2: "l", name: "m", link: "n"))

Now, in this latter example, I assumed that links was really an array, not a dictionary, but that's not really my point here. My key observation is that code is more readable and robust if you use proper custom types rather than just arrays and dictionaries.

And if you need to send and receive these model objects to some web service, you then map this model object to and from JSON. But use custom types for your actual model.


If you want to make the above types easily converted to and from JSON, you can use one of the object mapping libraries out there, so you can do something yourself, e.g.:

protocol Jsonable {
    var jsonObject: Any { get }
    init?(jsonObject: Any)
}

extension Foo: Jsonable {
    var jsonObject: Any {
        return [
            "id": id,
            "links": links?.map { $0.jsonObject } ?? [Any]()
        ]
    }

    init?(jsonObject: Any) {
        guard let dictionary = jsonObject as? [String: Any],
            let id = dictionary["id"] as? String else { return nil }

        var links: [Link]?
        if let linksDictionary = dictionary["links"] as? [Any] {
            links = linksDictionary.map { Link(jsonObject: $0)! }
        }

        self.init(id: id, links: links)
    }
}

extension Link: Jsonable {
    var jsonObject: Any { return [ "key1": key1, "key2": key2, "name": name, "link": link ] }

    init?(jsonObject: Any) {
        guard let dictionary = jsonObject as? [String: Any],
            let key1 = dictionary["key1"] as? String, 
            let key2 = dictionary["key2"] as? String, 
            let name = dictionary["name"] as? String, 
            let link = dictionary["link"] as? String else {
                return nil
        }
        self.init(key1: key1, key2: key2, name: name, link: link)
    }
}

Then you can do stuff like:

let object = try JSONSerialization.jsonObject(with: data)
var foo = Foo(jsonObject: object)!

Or:

foo.links?.append(Link(key1: "j", key2: "k", name: "l", link: "m"))

let data = try! JSONSerialization.data(withJSONObject: foo.jsonObject)

1 Comment

hello @Rob if possible please help me how to write a model class for this url json-generator.com/api/json/get/cwqUAMjKGa?indent=2 as I am a trainee don't know how to implement it on table view as mentioned in image shown here i.stack.imgur.com/26Lj8.png
0

This was the solution:

   var arrLinks : Array<Dictionary<String, Any>> = []

   for link in myArray {                
       var dict : Dictionary<String, Any> = [:]

       dict["key1"] = link.name
       dict["key2"] = link.ghostBefore
       dict["key3"] = link.ghostAfter

       arrLinks.append(dict)               
    }

    myDict["links"] = arrLinks as AnyObject

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.