Pistachiargo icon indicating copy to clipboard operation
Pistachiargo copied to clipboard

Pistachiargo and Value Transformers

Open rweindl opened this issue 9 years ago • 3 comments

Dear felixjendrusch, thank you very much for Pistachiargo! It would be create to provide a short example in your README how to combine the adapters with transformers. Right now I struggle to find a correct way of doing it.

For example: The server responds a URL as a String but I want to convert it to a NSURL. Below you see a short example. The resource adapter contains a url. The server responds the url as String. I want to save it as NSURL. Other useful examples would be the conversion of a ISO 8601 Date String to a NSDate object.

Would be great! Thanks and best regards from Munich.

Excerpt of JSONAdapters.swift

static let location = JSONAdapter(specification: [
    "id": JSONNumber(LocationLenses.id),
    "logos": JSONArray(LocationLenses.logos)(adapter: resource, model: Resource()),
])

static let resource = JSONAdapter(specification: [
    "url": JSONString(ResourceLenses.URL),
    "width": JSONNumber(ResourceLenses.width),
    "height": JSONNumber(ResourceLenses.height)
])

Excerpt of Resource.swift

@objc public class Resource: NSObject {
    // TODO: Change URL type to NSURL and implement adapter in JSONAdapters.swift
    public var URL: String
    public var width: Int
    public var height: Int

    public init(URL: String = "", width: Int = 0, height: Int = 0) {
        self.URL = URL
        self.width = width
        self.height = height
    }
}

struct ResourceLenses {
    static let URL = Lens(get: { $0.URL }, set: { (inout resource: Resource, URL) in
        resource.URL = URL
    })

    static let width = Lens(get: { $0.width }, set: { (inout resource: Resource, width) in
        resource.width = width
    })

    static let height = Lens(get: { $0.height }, set: { (inout resource: Resource, height) in
        resource.height = height
    })
}

rweindl avatar Mar 20 '15 13:03 rweindl

Hey @rweindl, I'm really sorry for the late reply! I was actually traveling at the time you opened this issue and must have accidentally marked the notification as read 😶

Regarding your issue, the JSONString lens transformer function is defined as follows:

public func JSONString<A>(lens: Lens<A, String>) -> Lens<Result<A, NSError>, Result<JSONValue, NSError>> {
    return transform(lens, JSONValueTransformers.string)
}

It uses the pre-defined JSONValueTransformers.string transformer, which is of type:

ValueTransformer<String, JSONValue, NSError>

So, when you call JSONString(ResourceLenses.URL), your lens of type Lens<Resource, String> is:

  1. transformed into a lens of type Lens<Result<Resource, NSError>, Result<String, NSError>>
  2. transformed into a lens of type Lens<Result<Resource, NSError>, Result<JSONValue, NSError>>

Both transformations are applied by transform. The second transformation uses the given value transformer (JSONValueTransformers.string), going from String to JSONValue. What's still missing is a value transformer going from NSURL to String, which should be something like this (untested, without error handling):

let NSURLValueTransformer = ValueTransformer(transformClosure: { value in
    return success(value.absoluteString)
}, reverseTransformClosure: { transformedValue in
    return success(NSURL(string: transformedValue)!)
})

Fortunately, value transformers can be composed very easily, so your adapter could be created like this:

let adapter = JSONAdapter(specification: [
    "url": transform(ResourceLenses.URL, NSURLValueTransformer >>> JSONValueTransformers.string),
    "width": JSONNumber(ResourceLenses.width),
    "height": JSONNumber(ResourceLenses.height)
])

I'm close to finally updating everything to Swift 1.2, including value transformers, the generic model framework itself and this particular instance. Thank you very much for your feedback, I will take that into account when updating the readme.

Please let me know if you have any other questions!

felixvisee avatar Apr 19 '15 21:04 felixvisee

Hey felixjendrusch, half a year later I realized your replied on that issue! Thank you very much for your very detailed explanation. I got it running with custom transformers. :+1:

Are you planning to continue working on Pistachiargo? (i.e. Swift 2 Branch) If not I would fork the project and start converting it to Swift 2.

Best regards Robert

rweindl avatar Nov 04 '15 11:11 rweindl

Yes, I would really like to continue working on Pistachio and related projects but my time for this is currently very limited 😐 I might start working on Swift 2 updates soon but cannot guarantee that.

felixvisee avatar Dec 03 '15 08:12 felixvisee