bignerdranch / Freddy

A reusable framework for parsing JSON in Swift.
MIT License
1.09k stars 119 forks source link

Possibility to append in case of inheritance #125

Closed Chewie69006 closed 8 years ago

Chewie69006 commented 8 years ago

Hi,

I tried to implement JSONEncodable on a class A, with 1 property. It was fine. But, B inherits from A, and add 2 properties. I'd like to append those properties to super.toJSON() but I couldn't.

I don't know if I'm missing something, or if it's completely impossible.

Thank you.

randomstep commented 8 years ago

I'm not sure if this is the preferred way to do it, but at a minimum you ought to be able to call super.toJSON(), get the dictionary or array back out of JSON, and add your keys.

What did you try so far? Including an example is always helpful.

Chewie69006 commented 8 years ago

Here is an example. I am beginning Swift development, and I'm a little confused, compared to Objective-C.

public class A : JSONEncodable {
    public var A:String

    func toJSON() -> JSON {
        return .Dictionary(["A": .String(A)])
    }
}

public final class B : A {
    public var B:String

    override func toJSON() -> JSON {
        var superJSON = super.toJSON()

        superJSON["B"] = .String(B) // What I am not able to do

        return superJSON
    } 
}
mdmathias commented 8 years ago

JSON's subscript is currently "get only". That means you cannot do something like superJSON["B"] = .String(B), which attempts to create a key-value pairing.

You will need to do something like this in the subclass:

override func toJSON() -> JSON {
    return .Dictionary(["A": .String(A), "B": .String(B)])
}
rafaelnobrepd commented 7 years ago

Had this issue, but the proposed solution looks worse than it can be. I did it this way, if it helps anyone:

func toJSON() -> JSON {
        var b = [String: JSON]()

        b["B"] = .string("B")

        if case .dictionary(let dict) = super.toJSON() {
            b.merge(with: dict)
        }
        return .dictionary(b)
    }
}

where merge is an extension defined as:

extension Dictionary {

    mutating func merge(with dictionary: Dictionary) {
        dictionary.forEach { updateValue($1, forKey: $0) }
    }

    func merged(with dictionary: Dictionary<Key,Value>) -> Dictionary<Key,Value> {
        var dict = self
        dict.merge(with: dictionary)
        return dict
    }

}