将JSON数据映射到Object(包括CoreData)
来源:互联网 发布:淘宝买的鲜花能退款吗 编辑:程序博客网 时间:2024/06/06 05:35
PropertyMapping
在进行数据的映射之前,我们需要定义Object(本文中所有Object都表示一个复杂的Object对象)中每一个property的映射关系PropertyMapping,其中ObjectMapping是标示当前property是否是一个Object,如果是nil,则表示当前property就是简单的映射。如果不是nil,则需要将property进行展开,把当前的property当成另外一个Object进行映射。
#import <Foundation/Foundation.h>@class ObjectMapping;@interface PropertyMapping : NSObject@property (nonatomic, weak) ObjectMapping *objectMapping;@property (nonatomic, copy) NSString *sourceKeyPath;@property (nonatomic, copy) NSString *destinationKeyPath;+ (PropertyMapping *)propertyMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(ObjectMapping *)mapping;@end
#import "PropertyMapping.h"@implementation PropertyMapping+ (PropertyMapping *)propertyMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(ObjectMapping *)mapping{ PropertyMapping *propertyMapping = [self new]; propertyMapping.sourceKeyPath = sourceKeyPath; propertyMapping.destinationKeyPath = destinationKeyPath; propertyMapping.objectMapping = mapping; return propertyMapping;}@end
ObjectMapping
ObjectMapping管理整个Object的PropertyMapping,包括objectClass,propertyMappings。并且提供Object反映射的inverseMapping。
#import <Foundation/Foundation.h>@class PropertyMapping;@interface ObjectMapping : NSObject- (ObjectMapping *) initWithClass:(Class) objectClass;- (ObjectMapping *) inverseMapping;- (void) addPropertyMapping:(PropertyMapping *) porpertyMapping;//add simple propertys - (void) addPropertyMappingsFromDictionary:(NSDictionary *) dic;@end
#import "ObjectMapping.h"@interface ObjectMapping ()@property (nonatomic, readwrite) Class objectClass;@property (nonatomic, readwrite) NSMutableArray *propertyMappings;@property (nonatomic, readwrite) NSMutableArray *mappedKeyPaths;@end@implementation ObjectMapping+ (instancetype)mappingForClass:(Class)objectClass{ return [[self alloc] initWithClass:objectClass];}- (id)initWithClass:(Class)objectClass{ self = [super init]; if (self) { self.objectClass = objectClass; self.propertyMappings = [NSMutableArray new]; self.mappedKeyPaths = [NSMutableArray new]; } return self;}- (void)addPropertyMapping:(PropertyMapping *)porpertyMapping{ NSAssert([self.mappedKeyPaths containsObject:porpertyMapping.destinationKeyPath] == NO, @"Unable to add mapping for keyPath %@, one already exists...", porpertyMapping.destinationKeyPath); NSAssert(self.propertyMappings, @"mutableRelationshipMappings is nil"); [self.mappedKeyPaths addObject:porpertyMapping.destinationKeyPath]; [self.propertyMappings addObject:porpertyMapping];}- (void)addPropertyMappingsFromDictionary:(NSDictionary *)dic{ for (NSString *attributeKeyPath in dic) { [self addPropertyMapping:[PropertyMapping propertyMappingFromKeyPath:attributeKeyPath toKeyPath:[dic objectForKey:attributeKeyPath] withMapping:nil]]; }}- (ObjectMapping *)inverseMapping{ ObjectMapping *inverseMapping = nil; inverseMapping = [ObjectMapping mappingForClass:[NSMutableDictionary class]]; for (PropertyMapping *propertyMapping in self.propertyMappings) { ObjectMapping *inverseRelationshipMapping = nil; if(propertyMapping.objectMapping && [propertyMapping.objectMapping isKindOfClass:[UPObjectMapping class]])//relationship mapping { inverseRelationshipMapping = [propertyMapping.objectMapping inverseMapping]; } [inverseMapping addPropertyMapping:[PropertyMapping propertyMappingFromKeyPath:propertyMapping.destinationKeyPath toKeyPath:propertyMapping.sourceKeyPath withMapping:inverseRelationshipMapping]]; } return inverseMapping;}@end
EntityMapping
EntityMapping从ObjectMapping继承,实现从JSONData到CoreData的映射。#import <Foundation/Foundation.h>#import "ObjectMapping.h"@class ObjectMapping;@interface EntityMapping : ObjectMapping@property (nonatomic, strong) NSEntityDescription *entity;- (id)initWithEntity:(NSEntityDescription *)entity;+ (instancetype)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(NSPersistentStore *)store;@end
#import "EntityMapping.h"@implementation EntityMapping- (id)initWithEntity:(NSEntityDescription *)entity{ NSParameterAssert(entity); Class objectClass = NSClassFromString([entity managedObjectClassName]); NSParameterAssert(objectClass); self = [self initWithClass:objectClass]; if (self) { self.entity = entity; } return self;}+ (instancetype)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(NSPersistentStore *)store{ NSParameterAssert(entityName); NSEntityDescription *entity = [[store.persistentStoreCoordinator.managedObjectModel entitiesByName] objectForKey:entityName]; NSAssert(entity, @"Unable to find an Entity with the name '%@' in the managed object model", entityName); return [[self alloc] initWithEntity:entity];}@end
MappingOperation
MappingOperation是整个映射的实现,包括从JSONData到Object和从Object到JSONData的映射。
#import <Foundation/Foundation.h>#import "ObjectMapping.h"@interface MappingOperation : NSObject+ (id) mapTargetObjectFromJSONData:(id)jsonData withMapping:(ObjectMapping *)mapping;+ (id) mapJSONDataFromTargetObject:(id)object withMapping:(ObjectMapping *)mapping;@end
#import "MappingOperation.h"@implementation MappingOperation+ (id) mapTargetObjectFromJSONData:(id) jsonData withMapping:(ObjectMapping *) mapping{ NSAssert(jsonData != nil, @"Cannot perform a mapping operation without a sourceObject object"); NSAssert(mapping != nil, @"Cannot perform a mapping operation without a mapping"); NSError *error = nil; id representation = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; if (error) { NSLog(@"%@", [error description]); return nil; } id mappingResult = [self mapTargetForRepresentation:representation withMapping:mapping]; return mappingResult;}+ (id) mapJSONDataFromTargetObject:(id) object withMapping:(ObjectMapping *) mapping{ NSAssert(object != nil, @"Cannot perform a mapping operation without a sourceObject object"); NSAssert(mapping != nil, @"Cannot perform a mapping operation without a mapping"); id inverseResult = [self mapJSONDatafromRepresentation:object withMapping:mapping]; NSError *error = nil; id jsonData = [NSJSONSerialization dataWithJSONObject:inverseResult options:NSJSONWritingPrettyPrinted error:&error]; if (error) { NSLog(@"%@", [error description]); return nil; } return jsonData;}#pragma private method+ (id) mapTargetForRepresentation:(id) representation withMapping:(ObjectMapping *) mapping{ if(!representation) { NSLog(@"Mapping data of %@ is nil.",mapping.objectClass); return nil; } //handle representation if it is NSArray or NSSet if([representation isKindOfClass:[NSArray class]] || [representation isKindOfClass:[NSSet class]]) { //NSLog(@"%i", [representation count]); NSMutableSet *set = [[NSMutableSet alloc]init]; for(NSDictionary *dic in representation) { [set addObject:[self mapTargetForRepresentation:dic withMapping:mapping]]; } return set; } NSObject *result = nil; if (![mapping isKindOfClass:[EntityMapping class]]) { result = [[mapping.objectClass alloc]init]; }else { EntityMapping *entityMapping = (EntityMapping *)mapping; NSEntityDescription *entity = [entityMapping entity]; NSString *keyAttribute = [mapping.objectClass keyAttribute]; if(keyAttribute && ![keyAttribute isEqualToString:@""]) { NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass(mapping.objectClass)]; for(UPPropertyMapping *map in mapping.propertyMappings) { if([map.destinationKeyPath isEqualToString:keyAttribute]) { request.predicate = [NSPredicate predicateWithFormat:@"%K=%@",keyAttribute,[representation valueForKey:map.sourceKeyPath]]; break; } } NSError *error = nil; NSArray *exists = [[NSManagedObjectContext contextForCurrentThread] executeFetchRequest:request error:&error]; if ([exists count] > 0) { // result = [exists objectAtIndex:0]; //NSLog(@"object exists:%@", [result valueForKey:keyAttribute]); }else { result = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:[NSManagedObjectContext contextForCurrentThread]]; } }else { result = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:[NSManagedObjectContext contextForCurrentThread]]; } } for(UPPropertyMapping *map in mapping.propertyMappings) { id value = [self getValueFromRepresentation:representation forKeyPath:map.sourceKeyPath]; if (map.objectMapping) { value = [self mapTargetForRepresentation:value withMapping:map.objectMapping]; } if ([value isKindOfClass:[NSNull class]]) { value = nil; } //[result setValue:value forKey:map.destinationKeyPath]; [self setObject:result withValue:value forKey:map.destinationKeyPath]; //NSLog(@"%@ = %@",map.destinationKeyPath,value); } return result;}+ (void) setObject:(id) object withValue:(id) value forKey:(NSString *) keyPath{ NSRange contain = [keyPath rangeOfString:@"."]; //check if the keyPath contains ".", if contain ,then break the keyPath into prefix and suffix if (contain.length > 0) { NSString *prefix = [keyPath substringToIndex:contain.location]; NSString *suffix = [keyPath substringFromIndex:contain.location + 1]; if([[object allKeys] containsObject:prefix])//check if the object has the property of prefix { // use the already exist property id property = [object valueForKey:prefix]; [self setObject:property withValue:value forKey:suffix]; }else { //add a property to the object, just handle simple object, can't handle managedobject. //so when design object mapping, can't add mapping like this @"class1.property":@"class2.property" when class2 is kind of managedobject id property = [[NSMutableDictionary alloc]init]; [self setObject:property withValue:value forKey:suffix]; [object setValue:property forKey:prefix]; } }else { //handle original property [object setValue:value forKey:keyPath]; }}+ (id) getValueFromRepresentation:(id) representation forKeyPath:(NSString *) keyPath{ NSRange contain = [keyPath rangeOfString:@"."]; //check if the keyPath contains ".", if contain ,then break the keyPath into prefix and suffix if (contain.length > 0) { NSString *prefix = [keyPath substringToIndex:contain.location]; NSString *suffix = [keyPath substringFromIndex:contain.location + 1]; return [self getValueFromRepresentation:[representation valueForKey:prefix] forKeyPath:suffix]; } //return original property value return [representation valueForKey:keyPath];}+ (id) mapJSONDatafromRepresentation:(id) representation withMapping:(ObjectMapping *) mapping{ if(!representation) { NSLog(@"Mapping data of %@ is nil.",mapping.objectClass); return nil; } //handle representation if it is NSArray or NSSet if([representation isKindOfClass:[NSArray class]] || [representation isKindOfClass:[NSSet class]]) { //NSLog(@"%i", [representation count]); NSMutableArray *array = [[NSMutableArray alloc]init]; for(NSDictionary *dic in representation) { [array addObject:[self mapJSONDatafromRepresentation:dic withMapping:mapping]]; } return array; } NSObject *result = [[mapping.objectClass alloc]init]; for(UPPropertyMapping *map in mapping.propertyMappings) { id value = nil; if (map.objectMapping) { value = [self mapJSONDatafromRepresentation:[representation valueForKey:map.sourceKeyPath] withMapping:map.objectMapping]; }else { value = [representation valueForKey:map.sourceKeyPath]; } [self setObject:result withValue:value forKey:map.destinationKeyPath]; } return result;}@end
- 将JSON数据映射到Object(包括CoreData)
- 将json数据映射到本地数据模型对象的一点想法
- 将MySQL数据映射到Memcached中
- 将MySQL数据映射到Memcached中
- 将MySQL数据映射到Memcached中
- 将MySQL数据映射到Memcached中
- 将关系数据映射到业务实体
- Java将json数据导入到excel
- 将json数据添加到数据库
- 将json数据映射成对象的处理办法
- 将MySQL数据映射到Memcached中 收藏
- RBD Image映射到Object
- ActionScript Object 到 Java Object 的映射
- 如何利用POST数据到web页面接口(包括调用页面发送json数据和页面后台接受json数据)
- python读取json文件,并将数据插入到mongodb
- 如何将json数据传入到Highcharts中的data中
- 如何将json数据传入到Highcharts中的data中
- 将json中的数据加载到table和ul中
- Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效
- Android优化
- 【下一个王朝——专业为王】
- UVA 1401 Remember the Word
- List of freely available programming books
- 将JSON数据映射到Object(包括CoreData)
- 纪念下 第一次开高速
- 数学之路(3)-机器学习(3)-机器学习算法-余弦相似度(1)
- 收集·总结(不断更新)
- What To Do When The Boss Begs You To Stay
- 黑马训练营-------------网络编程学习笔记
- 周流水-0831(茶水礼仪)
- Android与Mina集成
- ♫♪ Firework ♫♪