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

feat: support for swift codables #3434

Closed
sisoje opened this issue Aug 19, 2020 · 9 comments
Closed

feat: support for swift codables #3434

sisoje opened this issue Aug 19, 2020 · 9 comments
Milestone

Comments

@sisoje
Copy link

sisoje commented Aug 19, 2020

Feature Request

using swift codables for call.resolve()

Description

using swift codables for call.resolve()

Platform(s)

ios

Preferred Solution

using swift codables for call.resolve()

Alternatives

Additional Context

@sisoje sisoje changed the title feat: feat: support for swift codables Aug 19, 2020
@jcesarmobile
Copy link
Member

can you elaborate?

@sisoje
Copy link
Author

sisoje commented Aug 19, 2020

I can, currently resolve takes a dictionary [String:Any] as an argument here:

  func resolve(_ data: PluginResultData = [:]) {
    successHandler(CAPPluginCallResult(data), self)
  }

So I have to make a dictionary even though in reality we dont need a dictionary but a json object (json data/string) shown here:

  public func toJson() throws -> String {
    do {
      if JSONSerialization.isValidJSONObject(result) {
        let theJSONData = try JSONSerialization.data(withJSONObject: result, options: [])
        
        return String(data: theJSONData,
                      encoding: .utf8)!
      } else {
        CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." +
          "Ensure that all data passed to success callback from module method is JSON serializable!")
        throw JSProcessingError.jsonSerializeError(call: call)
      }
    } catch let error as JSProcessingError {
      throw error
    } catch {
      CAPLog.print("Unable to serialize plugin response as JSON: \(error.localizedDescription)")
    }
    
    return "{}"
  }
}

in ObjC language that was normal, but in Swift it is much better to use structures that conform to Codable (Encodable) so we can have compile time type safety.

I made an quick extension for that, but I'm not sure if its the best solution because we still do unnecesary data YOYO-ing because capacitor still requires [String:Any]:

extension CAPPluginCall {
    /**
     Converting swift encodable to the [String: Any] needed by capacitor
     */
    static func makePluginResultData<T: Encodable>(encodable: T) -> PluginResultData {
        let data = try! JSONEncoder().encode(encodable)
        return try! JSONSerialization.jsonObject(with: data) as! PluginResultData
    }

    func resolve<T: Encodable>(encodable: T) {
        resolve(Self.makePluginResultData(encodable: encodable))
    }
}

@sisoje
Copy link
Author

sisoje commented Aug 19, 2020

BTW call,error() also uses dictionaries, that could be extended to codables

@ikeith
Copy link
Contributor

ikeith commented Aug 19, 2020

This makes sense to me and I've had a similar thought. We do support Obj-C but prefer/encourage Swift so adding first-class support for its conventions where we can is valuable. I have started on updating some of the JS<->Native type wrangling here but intend to tackle some bigger refactoring after we have split apart the plugins. The extra serialization proposed here definitely has some drawbacks but I think it should be possible to build in a more efficient solution when updating the related code. I'm adding this to the 3.0 roadmap.

@ikeith ikeith added this to the 3.0.0 milestone Aug 19, 2020
@imhoffd imhoffd modified the milestones: 3.0.0, 3.1.0 Dec 8, 2020
@mzekrallah
Copy link

any update on this guys ? it's really important to have this flexibility i think.

@finnp
Copy link

finnp commented May 14, 2023

Are there any downsides of using JSON Encoder? Is it slower? It would save me some headaches if it just worked with Codable

@ettore
Copy link

ettore commented Jul 31, 2023

Any update on supporting Codable in Capacitor? It is definitely less than ideal to not being able to use it in CAPPluginCalls and notifications. Official docs do not mention it, I'm wondering if there is still a plan to support it. If not, it would be good to describe a workaround to be able to use Codable somehow (I'm guessing using let data = JSONSerialization.data(withJSONObject: call.dictionaryRepresentation) and then JSONDecoder().decode(data), although it seems very inefficient assuming it even works reliably.)

@jcesarmobile
Copy link
Member

implemented on #7119

Copy link

ionitron-bot bot commented Jan 14, 2024

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Jan 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Development

No branches or pull requests

8 participants