Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle in polymorphism #34

Closed
lancy opened this issue Apr 17, 2015 · 3 comments
Closed

How to handle in polymorphism #34

lancy opened this issue Apr 17, 2015 · 3 comments
Labels

Comments

@lancy
Copy link

lancy commented Apr 17, 2015

Suppose I have a base class named Accessory, and there are some subclass inherit from it, like AudioAccessory, LabelAccessory, ContentAccessory, and a type to identify them.

class Accessory {
    var type: Int
}

class LabelAccessory: Accessory {
    var label: String
}

class ContentAccessory: Accessory {
    var content: String
}

How do I convert a JSON into [Accessory] ?
Should I write my custom deserialisation function, switch type to init object in different class? something like:

public func <-- (inout instance: [Accessory]?, dataObject: AnyObject?) --> [Accessory]? {
  if let dataArray = dataObject as? [JSONDictionary] {
    array = [Accessory]()
    for data in dataArray {
        let baseObject = Accessory(data: data)
        switch baseObject.type {
            case Label:
                array!.append(LabelAccessory(data: data))
                .....
       }
    }
  } else {
    array = nil
  }
  return array
}

Is there a better way to do that?
Thank you so much

@lancy
Copy link
Author

lancy commented Apr 17, 2015

One more question:
Is there a way to deserialise enum type?

enum AccessoryType: Int {
    case Label = 0
    case Content = 1
}

// It doesn't work
type <-- data["type"]

@isair
Copy link
Owner

isair commented Apr 17, 2015

You can either extend the deserialization operator like that or write a single function that deserializes given data and returns the appropriate object based on the type parameter and use it everywhere. Here is an adapted version of a function I use in one of my projects to deserialize a single object based on a type parameter.

func deserializeAccessoryBasedOnTypeParameter(jsonObject: AnyObject?) -> Accessory? {
  if let jsonDictionary = jsonObject as? JSONDictionary {
    var accessoryTypeRawValue = -1
    accessoryTypeRawValue <-- jsonDictionary["type"]
    if let accessoryType = AccessoryType(rawValue: accessoryTypeRawValue) {
      switch accessoryType {
      case .Label:
        return LabelAccessory(data: jsonDictionary)
      case .Content:
        return ContentAccessory(data: jsonDictionary)
      }
    }
  }
  return nil
}

Cast the data you receive to type [JSONDictionary] and then loop through it and deserialize objects using this function. So you can make the function directly accept a JSONDictionary parameter if you want to. The original function I use accepts AnyObject? and returns AnyObject? as it can return any one of the several model objects I use inside my project. Also, using this method, you don't need to store type inside your models.

About enum deserialization support, I was planning to add it this weekend but I seem to have luckily got a pull request that implements it. You can checkout the source repo of that pull request if you need enum deserialization ASAP. The next version will be released tomorrow though.

@isair isair added the question label Apr 17, 2015
@lancy
Copy link
Author

lancy commented Apr 18, 2015

I do love the deserialization operator you created.

In my project, there are more than one place that I need to deserialize an array of Accessory, I don't want to loop it every time. So I decide to extent the operator.
Now I can do something just like the usual:

accessories <-- data["accessories"]

Thanks for your help, and it's a brilliant project.

@lancy lancy closed this as completed Apr 18, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants