') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - Jack-s/EasyMapping: The easiest way to marshall and unmarshall Dictionary representations such as JSON representation · GitHub
Skip to content

Repository files navigation

EasyMapping

An easy way to unmarshall a Dictionary of attributes (which came from JSON, XML or just a NSDictionary) into a Class and vice versa.

##Contact:

Developed by Lucas Medeiros E-mail: lucastoc@gmail.com

Development requirements

Install cocoapods

To install cocoapods you will need ruby.

gem install cocoapods

More information about cocoapods:

Cocoapods

Add the dependency to your Podfile:

platform:ios
...
pod'EasyMapping','~>0.4.9'

Run pod install to install the dependencies.

Usage

  • Supose you have these classes:
typedefenum {
GenderMale,
GenderFemale
} Gender;
@interfacePerson : NSObject@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *email;
@property (nonatomic, assign) Gender gender;
@property (nonatomic, strong) Car *car;
@property (nonatomic, strong) NSArray *phones;
@end@interfaceCar : NSObject@property (nonatomic, copy) NSString *model;
@property (nonatomic, copy) NSString *year;
@property (nonatomic, strong) NSDate *createdAt;
@end@interfacePhone : NSObject@property (nonatomic, copy) NSString *DDI;
@property (nonatomic, copy) NSString *DDD;
@property (nonatomic, copy) NSString *number;
@end@interfaceNative : NSObject@property (nonatomic, readwrite) NSInteger integerProperty;
@property (nonatomic, readwrite) NSUInteger unsignedIntegerProperty;
@property (nonatomic, readwrite) CGFloat cgFloatProperty;
@property (nonatomic, readwrite) double doubleProperty;
@property (nonatomic, readwrite) BOOL boolProperty;
@end
  • Map your classes in any place you want. An example:
#import"MappingProvider.h"
#import"Car.h"
#import"Phone.h"
#import"Person.h"
#import"Address.h"@implementationMappingProvider
+ (EKObjectMapping *)carMapping
{
return [EKObjectMapping mappingForClass:[Car class] withBlock:^(EKObjectMapping *mapping) {
[mapping mapFieldsFromArray:@[@"model", @"year"]];
[mapping mapKey:@"created_at"toField:@"createdAt"withDateFormat:@"yyyy-MM-dd"];
}];
}
+ (EKObjectMapping *)phoneMapping
{
return [EKObjectMapping mappingForClass:[Phone class] withBlock:^(EKObjectMapping *mapping) {
[mapping mapFieldsFromArray:@[@"number"]];
[mapping mapFieldsFromDictionary:@{
@"ddi" : @"DDI",
@"ddd" : @"DDD"
}];
}];
}
+ (EKObjectMapping *)personMapping
{
return [EKObjectMapping mappingForClass:[Person class] withBlock:^(EKObjectMapping *mapping) {
NSDictionary *genders = @{ @"male": @(GenderMale), @"female": @(GenderFemale) };
[mapping mapFieldsFromArray:@[@"name", @"email"]];
[mapping mapKey:@"gender"toField:@"gender"withValueBlock:^(NSString *key, id value) {
return genders[value];
} withReverseBlock:^id(id value) {
return [genders allKeysForObject:value].lastObject;
}];
[mapping hasOneMapping:[selfcarMapping] forKey:@"car"];
[mapping hasManyMapping:[selfphoneMapping] forKey:@"phones"];
}];
}
+ (EKObjectMapping *)nativeMapping
{
return [EKObjectMapping mappingForClass:[Native class] withBlock:^(EKObjectMapping *mapping) {
[mapping mapFieldsFromArray:@[
@"integerProperty", @"unsignedIntegerProperty", @"cgFloatProperty", @"doubleProperty", @"boolProperty"
]];
}];
}
  • Converting a NSDictionary or NSArray to a object class or collection now becomes easy:
Person *person = [EKMapper objectFromExternalRepresentation:personRepresentation withMapping:[MappingProvider personMapping]];
NSArray *carsArray = [EKMapper arrayOfObjectsFromExternalRepresentation:carsRepresentation withMapping:[MappingProvider carMapping]];
  • Converting an object/collection to NSDictionary/NSArray:
NSDictionary *representation = [EKSerializer serializeObject:car withMapping:[MappingProvider carMapping]];
NSArray *collectionRepresentation = [EKSerializer serializeCollection:cars withMapping:[MappingProvider carMapping]];
  • Filling an existent object:

Supose you have something like this:

 Person *person = [Person alloc] init] 

To fill an already instantiated object you can do this:

[EKMapper fillObject:person fromExternalRepresentation:personRepresentation withMapping:[Mappings personMapping]];
  • See the specs code

CoreData

If you are using CoreData objects use EKManagedObjectMapping instead of EKObjectMapping.

Thanks

Thanks to:

  • basitali who added the fillObject functionality on EKMapper!
  • Alejandro who added CoreData support!
  • DenHeadless who added the ability to use different naming in hasOne and hasMany mappings!
  • ArtFeel who added the ability to serialization/deserialization of primitive types!
  • Dany L'Hébreux who added the NSSet support!

Requirements

EasyMapping requires iOS 5.x or greater.

Usage is provided under the MIT License. See LICENSE for the full details.

The idea

The idea came from:

  • RestiKit's mapping, its problem is that it doesn't transform custom values (such as a string value to an enum)
  • Mantle's mapping, but you don't need to inherit from any class

About

The easiest way to marshall and unmarshall Dictionary representations such as JSON representation

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages