nfls
nfls

Reputation: 318

RestKit - Multi-type subarray mapping

I'm using RestKit to map JSON objects in my iOS project. So far everything works fine, but I'm having trouble mapping a subarray of custom types.

The JSON looks as such:

{ "Result" : "OK", "Total": "1","content": [ 
    {"article": 
        {
        "title": "sample_title",
        "author": "sample_author",
        "article_details": [
            {"text": 
                {
                "body": "sample_body",
                }
            },
            {"image": 
                {
                "image": "sample_image"
                }
            },
            {"quote": 
                {
                "quote": "sample_quote",
                }
            }
            {"text": 
                {
                "body": "sample_body",
                }
            },
        ]}
    }]
}

Note that article_detail objects types can appear in any number or order. Futhermore, it is important to note that I need to store the order in which these objects appear, and each of its types.

To do so, and to simplify data manipulation, I auto generated two NSManagedObjects, using CoreData. Something as follows:

extension Article {
    public var title: String?
    public var author: String?
    public var details: NSOrderedSet?
}

extension ArticleDetail {
    public var body: String?
    public var image: String?
    public var quote: String?
}

My mappings are the following:

//Detail mapping
let detailsMapping = RKEntityMapping(forEntityForName: "ArticleDetail", in: objectManager.managedObjectStore)
detailsMapping?.addAttributeMappings(from: [
    "image"     : "image",
    "body"      : "body",
    "quote"     : "quote",
    ]
)

//Article mapping
let articleMapping = RKEntityMapping(forEntityForName: "Article", in: objectManager.managedObjectStore)
articleMapping?.addAttributeMappings(from: [
    "title"          : "title",
    "author"         : "author",
    ]
)

//Relation mapping
articleMapping!.addPropertyMapping(RKRelationshipMapping(fromKeyPath: "article_details.text", toKeyPath: "details", with: detailsMapping))

//Response descriptior
let articleResponseDescriptor = RKResponseDescriptor(
    mapping: articleMapping,
    method: RKRequestMethod.GET,
    pathPattern: nil,
    keyPath: "content.article",
    statusCodes: IndexSet(integer: 200)
)
objectManager.addResponseDescriptor(articleResponseDescriptor)

This works fine for the article info. However, as expected, due to

fromKeyPath: "article_details.text"

it only maps "text" objects.

Identifying the type is easy, checking which parameters are nil in the article detail object.

A similar problem can be found in RestKit - Map keypath of an array to the object inside of that array

How can I accomplish this in Swift, using RestKit?

Thank you very much.

-N

Upvotes: 0

Views: 84

Answers (1)

nfls
nfls

Reputation: 318

I managed to solve this issue yesterday. I used a class as a "wrapper" for each custom object.

So, the article simply contains an ordered set of Wrappers, saving the order if these objects, and the wrapper contains an article detail. Like so:

extension Article {
    public var title: String?
    public var author: String?
    public var details: NSOrderedSet?
}

extension ArticleWrapper {
    public var app_text: ArticleTextDetail?
    public var app_image: ArticleImageDetail?
    public var app_quote: ArticleQuoteDetail?
}

extension ArticleTextDetail {
    ...
}    

extension ArticleImageDetail {
    ...
}  

extension ArticleQuoteDetail {
    ...
} 

The mappings look as such:

let wrapperMapping = RKEntityMapping(forEntityForName: "ArticleWrapper", in: objectManager.managedObjectStore)


let textMapping = RKEntityMapping(forEntityForName: "ArticleTextDetail", in: objectManager.managedObjectStore)
...

let imageMapping = RKEntityMapping(forEntityForName: "ArticleImageDetail", in: objectManager.managedObjectStore)
...

let quoteMapping = RKEntityMapping(forEntityForName: "ArticleQuoteDetail", in: objectManager.managedObjectStore)
...

let articleMapping = RKEntityMapping(forEntityForName: "Article", in: objectManager.managedObjectStore)
articleMapping?.addAttributeMappings(from: [
"title"          : "title",
"author"         : "author",
    ]
)

wrapperMapping!.addPropertyMapping(RKRelationshipMapping(fromKeyPath: "text", toKeyPath: "app_text", with: textMapping))
wrapperMapping!.addPropertyMapping(RKRelationshipMapping(fromKeyPath: "image", toKeyPath: "app_image", with: imageMapping))
wrapperMapping!.addPropertyMapping(RKRelationshipMapping(fromKeyPath: "quote", toKeyPath: "app_quote", with: quoteMapping))

articleMapping!.addPropertyMapping(RKRelationshipMapping(fromKeyPath: "article_details", toKeyPath: "details", with: wrapperMapping))

Everything works as intended now.

Thanks.

-N

Upvotes: 0

Related Questions