mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-05-06 08:53:25 +08:00
Overhaul RKParser API's for clarity and simplicity:
* Adds support for NSJSONSerialization. closes #476 * Renames RKParser to RKSerialization * Renames RKParserRegistry to RKMIMETypeSerialization * Rework serialization implementations API's to use class methods * Fold together string and regular expression matching for MIME Type registrations * Port serialization implementations to working off of NSData instead of NSString. refs #762 * Migrate JSONKit to being an optional component. See https://github.com/RestKit/RKJSONKitSerialization
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
#import "RKObjectMapping.h"
|
||||
#import "RKAttributeMapping.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
#import "RKObjectParameters.h"
|
||||
#import "RKObjectParameterization.h"
|
||||
#import "RKMappingResult.h"
|
||||
#import "RKObjectMapper.h"
|
||||
#import "RKParserRegistry.h"
|
||||
#import "RKMIMETypeSerialization.h"
|
||||
|
||||
109
Code/ObjectMapping/RKMIMETypeSerialization.h
Normal file
109
Code/ObjectMapping/RKMIMETypeSerialization.h
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// RKMIMETypeSerialization.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 5/18/11.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import "RKMIMETypes.h"
|
||||
#import "RKSerialization.h"
|
||||
|
||||
/**
|
||||
The RKMIMETypeSerialization class provides support for the registration of classes
|
||||
conforming to the RKSerialization protocol by MIME Type and the serialization and
|
||||
deserialization of content by MIME Type. Serialization implementations may be registered
|
||||
by an exact string match (i.e. 'application/json' for a JSON serialization implementation)
|
||||
or by regular expression to match MIME Type by pattern.
|
||||
*/
|
||||
@interface RKMIMETypeSerialization : NSObject
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
/// @name Managing MIME Type Registrations
|
||||
///-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Registers the given serialization class to handle content for the given MIME Type identifier.
|
||||
|
||||
MIME Types may be given as either a string or as a regular expression that matches the MIME Types for which the
|
||||
given serialization should handle. Serializations are searched in the reverse order of their registration. If a registration
|
||||
is made for an already registered MIME Type, the new registration will take precedence.
|
||||
|
||||
@param serializationClass The class conforming to the RKSerialization protocol to be registered as handling the given MIME Type.
|
||||
@param MIMETypeStringOrRegularExpression A string or regular expression specifying the MIME Type(s) that given serialization
|
||||
implementation is to be registered as handling.
|
||||
*/
|
||||
+ (void)registerClass:(Class<RKSerialization>)serializationClass forMIMEType:(id)MIMETypeStringOrRegularExpression;
|
||||
|
||||
/**
|
||||
Unregisters the given serialization class from handling any MIME Types.
|
||||
|
||||
After this method is invoked, invocations of `serializationForMIMEType:` will no longer return the unregistered
|
||||
serialization class.
|
||||
|
||||
@param serializationClass The class conforming to the RKSerialization protocol to be unregistered.
|
||||
*/
|
||||
+ (void)unregisterClass:(Class<RKSerialization>)serializationClass;
|
||||
|
||||
/**
|
||||
Returns the serialization class registered to handle the given MIME Type.
|
||||
|
||||
Searches the registrations in reverse order for the first serialization implementation registered to handle
|
||||
the given MIME Type. Matches are determined by doing a lowercase string comparison if the MIME Type was registered
|
||||
with a string identifier or by evaluating a regular expression match against the given MIME Type if registered with
|
||||
a regular expression.
|
||||
|
||||
@param MIMEType The MIME Type for which to return the registered RKSerialization conformant class.
|
||||
@return A class conforming to the RKSerialization protocol registered for the given MIME Type or nil if none was found.
|
||||
*/
|
||||
+ (Class<RKSerialization>)serializationClassForMIMEType:(NSString *)MIMEType;
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
/// @name Serializing and Deserializing Content by MIME Type
|
||||
///-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Deserializes and returns a Foundation object representation of the given UTF-8 encoded data in
|
||||
the serialization format for the given MIME Type.
|
||||
|
||||
On invocation, searches the registrations by invoking `serializationClassForMIMEType:` with the given
|
||||
MIME Type and then invokes `objectFromData:error:` on the RKSerialization conformant class returned. If
|
||||
no serialization implementation is found to handle the given MIME Type, nil is returned and the given
|
||||
error pointer will be set to an NSError object with the `RKMissingSerializationForMIMETypeError` code.
|
||||
|
||||
@param data The UTF-8 encoded data representation of the object to be deserialized.
|
||||
@param MIMEType The MIME Type of the serialization format the data is in.
|
||||
@param error A pointer to an NSError object.
|
||||
@return A Foundation object from the serialized data in data, or nil if an error occurs.
|
||||
*/
|
||||
+ (id)objectFromData:(NSData *)data MIMEType:(NSString *)MIMEType error:(NSError **)error;
|
||||
|
||||
/**
|
||||
Serializes and returns a UTF-8 encoded data representation of the given Foundation
|
||||
object in the serialization format for the given MIME Type.
|
||||
|
||||
On invocation, searches the registrations by invoking `serializationClassForMIMEType:` with the given
|
||||
MIME Type and then invokes `objectFromData:error:` on the RKSerialization conformant class returned. If
|
||||
no serialization implementation is found to handle the given MIME Type, nil is returned and the given
|
||||
error pointer will be set to an NSError object with the `RKMissingSerializationForMIMETypeError` code.
|
||||
|
||||
@param data The UTF-8 encoded data representation of the object to be deserialized.
|
||||
@param MIMEType The MIME Type of the serialization format the data is in.
|
||||
@param error A pointer to an NSError object.
|
||||
@return A Foundation object from the serialized data in data, or nil if an error occurs.
|
||||
*/
|
||||
+ (NSData *)dataFromObject:(id)object MIMEType:(NSString *)MIMEType error:(NSError **)error;
|
||||
|
||||
@end
|
||||
178
Code/ObjectMapping/RKMIMETypeSerialization.m
Normal file
178
Code/ObjectMapping/RKMIMETypeSerialization.m
Normal file
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// RKMIMETypeSerialization.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 5/18/11.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import "RKMIMETypeSerialization.h"
|
||||
#import "RKErrors.h"
|
||||
#import "RKSerialization.h"
|
||||
#import "RKLog.h"
|
||||
|
||||
// Define logging component
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent lcl_cRestKitSupport
|
||||
|
||||
@interface RKMIMETypeSerializationRegistration : NSObject
|
||||
|
||||
@property (nonatomic, strong) id MIMETypeStringOrRegularExpression;
|
||||
@property (nonatomic, assign) Class<RKSerialization> serializationClass;
|
||||
|
||||
- (id)initWithMIMEType:(id)MIMETypeStringOrRegularExpression serializationClass:(Class<RKSerialization>)serializationClass;
|
||||
- (BOOL)matchesMIMEType:(NSString *)MIMEType;
|
||||
@end
|
||||
|
||||
@implementation RKMIMETypeSerializationRegistration
|
||||
|
||||
- (id)initWithMIMEType:(id)MIMETypeStringOrRegularExpression serializationClass:(Class<RKSerialization>)serializationClass
|
||||
{
|
||||
NSParameterAssert(MIMETypeStringOrRegularExpression);
|
||||
NSParameterAssert(serializationClass);
|
||||
NSAssert([MIMETypeStringOrRegularExpression isKindOfClass:[NSString class]]
|
||||
|| [MIMETypeStringOrRegularExpression isKindOfClass:[NSRegularExpression class]],
|
||||
@"Can only register a serialization class for a MIME Type by string or regular expression.");
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.MIMETypeStringOrRegularExpression = MIMETypeStringOrRegularExpression;
|
||||
self.serializationClass = serializationClass;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)matchesMIMEType:(NSString *)MIMEType
|
||||
{
|
||||
if ([self.MIMETypeStringOrRegularExpression isKindOfClass:[NSString class]]) {
|
||||
return [[MIMEType lowercaseString] isEqualToString:[self.MIMETypeStringOrRegularExpression lowercaseString]];
|
||||
} else if ([self.MIMETypeStringOrRegularExpression isKindOfClass:[NSRegularExpression class]]) {
|
||||
NSRegularExpression *regex = (NSRegularExpression *) self.MIMETypeStringOrRegularExpression;
|
||||
NSUInteger numberOfMatches = [regex numberOfMatchesInString:[MIMEType lowercaseString] options:0 range:NSMakeRange(0, [MIMEType length])];
|
||||
return numberOfMatches > 0;
|
||||
} else {
|
||||
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Unable to evaluate match for MIME Type '%@': expected an NSSt" userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RKMIMETypeSerialization ()
|
||||
@property (nonatomic, strong) NSMutableArray *registrations;
|
||||
@end
|
||||
|
||||
@implementation RKMIMETypeSerialization
|
||||
|
||||
+ (RKMIMETypeSerialization *)sharedSerialization {
|
||||
static RKMIMETypeSerialization *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[RKMIMETypeSerialization alloc] init];
|
||||
[sharedInstance addRegistrationsForKnownSerializations];
|
||||
});
|
||||
return sharedInstance;
|
||||
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.registrations = [NSMutableArray new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addRegistrationsForKnownSerializations {
|
||||
Class serializationClass = nil;
|
||||
|
||||
// JSON
|
||||
NSArray *JSONSerializationClassNames = @[ @"RKNSJSONSerialization", @"RKJSONKitSerialization" ];
|
||||
for (NSString *serializationClassName in JSONSerializationClassNames) {
|
||||
serializationClass = NSClassFromString(serializationClassName);
|
||||
if (serializationClass) {
|
||||
RKLogInfo(@"JSON Serialization class '%@' detected: Registering for MIME Type '%@", serializationClassName, RKMIMETypeJSON);
|
||||
[self.registrations addObject:[[RKMIMETypeSerializationRegistration alloc] initWithMIMEType:RKMIMETypeJSON serializationClass:serializationClass]];
|
||||
}
|
||||
}
|
||||
|
||||
// XML
|
||||
// parserClass = NSClassFromString(@"RKXMLParserXMLReader");
|
||||
// if (parserClass) {
|
||||
// [self setParserClass:parserClass forMIMEType:RKMIMETypeXML];
|
||||
// [self setParserClass:parserClass forMIMEType:RKMIMETypeTextXML];
|
||||
// }
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
+ (Class<RKSerialization>)serializationClassForMIMEType:(NSString *)MIMEType
|
||||
{
|
||||
for (RKMIMETypeSerializationRegistration *registration in [[self sharedSerialization].registrations reverseObjectEnumerator]) {
|
||||
if ([registration matchesMIMEType:MIMEType]) {
|
||||
return registration.serializationClass;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)registerClass:(Class<RKSerialization>)serializationClass forMIMEType:(id)MIMETypeStringOrRegularExpression
|
||||
{
|
||||
RKMIMETypeSerializationRegistration *registration = [[RKMIMETypeSerializationRegistration alloc] initWithMIMEType:MIMETypeStringOrRegularExpression serializationClass:serializationClass];
|
||||
[[self sharedSerialization].registrations addObject:registration];
|
||||
}
|
||||
|
||||
+ (void)unregisterClass:(Class<RKSerialization>)serializationClass
|
||||
{
|
||||
NSArray *registrationsCopy = [[self sharedSerialization].registrations copy];
|
||||
for (RKMIMETypeSerializationRegistration *registration in registrationsCopy) {
|
||||
if (registration.class == serializationClass) {
|
||||
[[self sharedSerialization].registrations removeObject:registration];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (id)objectFromData:(NSData *)data MIMEType:(NSString *)MIMEType error:(NSError **)error
|
||||
{
|
||||
Class<RKSerialization> serializationClass = [self serializationClassForMIMEType:MIMEType];
|
||||
if (!serializationClass) {
|
||||
if (error) {
|
||||
NSString* errorMessage = [NSString stringWithFormat:@"Cannot deserialize data: No serialization registered for MIME Type '%@'", MIMEType];
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : errorMessage, RKMIMETypeErrorKey : MIMEType };
|
||||
*error = [NSError errorWithDomain:RKErrorDomain code:RKUnsupportedMIMETypeError userInfo:userInfo];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [serializationClass objectFromData:data error:error];
|
||||
}
|
||||
|
||||
+ (id)dataFromObject:(id)object MIMEType:(NSString *)MIMEType error:(NSError **)error
|
||||
{
|
||||
Class<RKSerialization> serializationClass = [self serializationClassForMIMEType:MIMEType];
|
||||
if (!serializationClass) {
|
||||
if (error) {
|
||||
NSString* errorMessage = [NSString stringWithFormat:@"Cannot deserialize data: No serialization registered for MIME Type '%@'", MIMEType];
|
||||
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : errorMessage, RKMIMETypeErrorKey : MIMEType };
|
||||
*error = [NSError errorWithDomain:RKErrorDomain code:RKUnsupportedMIMETypeError userInfo:userInfo];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [serializationClass dataFromObject:object error:error];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,153 +0,0 @@
|
||||
//
|
||||
// RKParserRegistry.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 5/18/11.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import "RKMIMETypes.h"
|
||||
#import "RKParser.h"
|
||||
|
||||
/**
|
||||
RKParserRegistry provides for the registration of RKParser classes
|
||||
that handle parsing/serializing for content by MIME Type. Registration
|
||||
is configured via exact string matches (i.e. application/json) or via regular
|
||||
expression.
|
||||
*/
|
||||
@interface RKParserRegistry : NSObject {
|
||||
NSMutableDictionary *_MIMETypeToParserClasses;
|
||||
NSMutableArray *_MIMETypeToParserClassesRegularExpressions;
|
||||
NSData *_whitespaceData;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the global shared singleton registry for MIME Type to Parsers
|
||||
|
||||
@return The global shared RKParserRegistry instance.
|
||||
*/
|
||||
+ (RKParserRegistry *)sharedRegistry;
|
||||
|
||||
/**
|
||||
Sets the global shared registry singleton to a new instance of RKParserRegistry
|
||||
|
||||
@param registry A new parser registry object to configure as the shared instance.
|
||||
*/
|
||||
+ (void)setSharedRegistry:(RKParserRegistry *)registry;
|
||||
|
||||
/**
|
||||
Returns the parsed data by delegating to a registered parser for the specified
|
||||
MIME type.
|
||||
|
||||
If the data cannot be handled directly by the parser, it is first converted to
|
||||
a string and subsequently passed to the parser.
|
||||
|
||||
@param data The data to be parsed.
|
||||
@param MIMEType The MIME Type of the content to be parsed.
|
||||
@param encoding The NSStringEncoding to use when converting the data to string.
|
||||
@param error A pointer to an NSError object.
|
||||
@return The parsed object or nil if an error occurred during parsing.
|
||||
*/
|
||||
- (id)parseData:(NSData *)data withMIMEType:(NSString *)MIMEType encoding:(NSStringEncoding)encoding error:(NSError **)error;
|
||||
|
||||
/**
|
||||
Returns the parsed data by delegating to a registered parser for the specified
|
||||
MIME type.
|
||||
|
||||
This simply invokes parseData:withMIMEType:encoding:error: with a NSUTF8StringEncoding.
|
||||
|
||||
@param data The data to be parsed.
|
||||
@param MIMEType The MIME Type of the content to be parsed.
|
||||
@param error A pointer to an NSError object.
|
||||
@return The parsed object or nil if an error occurred during parsing.
|
||||
*/
|
||||
- (id)parseData:(NSData *)data withMIMEType:(NSString *)MIMEType error:(NSError **)error;
|
||||
|
||||
/**
|
||||
Returns the serialized data by delegating to a registered parser for the specified
|
||||
MIME type.
|
||||
|
||||
If the parser is only able to serialize to string, the serialized string will
|
||||
be converted to NSData.
|
||||
|
||||
@param object The object to be serialized.
|
||||
@param MIMEType The desired MIME Type for the serialized output.
|
||||
@param error A pointer to an NSError object.
|
||||
@return The serialized object or nil if an error occurred during serialization.
|
||||
*/
|
||||
- (NSData *)serializeObject:(id)object forMIMEType:(NSString *)MIMEType error:(NSError **)error;
|
||||
|
||||
/**
|
||||
Returns an instance of the RKParser conformant class registered to handle content
|
||||
with the given MIME Type.
|
||||
|
||||
MIME Types are searched in the order in which they are registered and exact
|
||||
string matches are favored over regular expressions.
|
||||
|
||||
@param MIMEType The MIME Type of the content to be parsed/serialized.
|
||||
@return An instance of the RKParser conformant class registered to handle the given MIME Type.
|
||||
*/
|
||||
- (id<RKParser>)parserForMIMEType:(NSString *)MIMEType;
|
||||
|
||||
/**
|
||||
Returns an instance of the RKParser conformant class registered to handle content
|
||||
with the given MIME Type.
|
||||
|
||||
MIME Types are searched in the order in which they are registered and exact
|
||||
string matches are favored over regular expressions.
|
||||
|
||||
@param MIMEType The MIME Type of the content to be parsed/serialized.
|
||||
@return The RKParser conformant class registered to handle the given MIME Type.
|
||||
*/
|
||||
- (Class<RKParser>)parserClassForMIMEType:(NSString *)MIMEType;
|
||||
|
||||
/**
|
||||
Registers an RKParser conformant class as the handler for MIME Types exactly matching the
|
||||
specified MIME Type string.
|
||||
|
||||
@param parserClass The RKParser conformant class to instantiate when parsing/serializing MIME Types matching MIMETypeExpression.
|
||||
@param MIMEType A MIME Type string for which instances of parserClass should be used for parsing/serialization.
|
||||
*/
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMEType:(NSString *)MIMEType;
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
|
||||
/**
|
||||
Registers an RKParser conformant class as the handler for MIME Types matching the
|
||||
specified regular expression.
|
||||
|
||||
@param parserClass The RKParser conformant class to instantiate when parsing/serializing MIME Types matching MIMETypeExpression.
|
||||
@param MIMETypeRegex A regular expression that matches MIME Types that should be handled by instances of parserClass.
|
||||
*/
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMETypeRegularExpression:(NSRegularExpression *)MIMETypeRegex;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
Returns wether the registry has a registered parser for that MIME type.
|
||||
|
||||
@param MIMEType The MIME type to test if it is parsable.
|
||||
@return YES if a registered parser for that MIME type is registered, NO otherwise.
|
||||
*/
|
||||
- (BOOL)canParseMIMEType:(NSString*)MIMEType;
|
||||
|
||||
/**
|
||||
Automatically configure the registry via run-time reflection of the RKParser classes
|
||||
available that ship with RestKit. This happens automatically when the shared registry
|
||||
singleton is initialized and makes configuration transparent to users.
|
||||
*/
|
||||
- (void)autoconfigure;
|
||||
|
||||
@end
|
||||
@@ -1,160 +0,0 @@
|
||||
//
|
||||
// RKParserRegistry.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 5/18/11.
|
||||
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#import "RKParserRegistry.h"
|
||||
#import "RKErrors.h"
|
||||
|
||||
RKParserRegistry *gSharedRegistry;
|
||||
|
||||
@implementation RKParserRegistry
|
||||
|
||||
+ (RKParserRegistry *)sharedRegistry {
|
||||
if (gSharedRegistry == nil) {
|
||||
gSharedRegistry = [RKParserRegistry new];
|
||||
[gSharedRegistry autoconfigure];
|
||||
}
|
||||
|
||||
return gSharedRegistry;
|
||||
}
|
||||
|
||||
+ (void)setSharedRegistry:(RKParserRegistry *)registry {
|
||||
gSharedRegistry = registry;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_MIMETypeToParserClasses = [[NSMutableDictionary alloc] init];
|
||||
_MIMETypeToParserClassesRegularExpressions = [[NSMutableArray alloc] init];
|
||||
_whitespaceData = [[NSData alloc] initWithBytes:" " length:1];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)parseData:(NSData *)data withMIMEType:(NSString *)MIMEType encoding:(NSStringEncoding)encoding error:(NSError **)error {
|
||||
// Handle empty data and data containing a single whitespace character:
|
||||
NSUInteger length = [data length];
|
||||
if (length == 0 || (length == 1 && [data isEqualToData:_whitespaceData])) {
|
||||
if (error) {
|
||||
NSString* errorMessage = [NSString stringWithFormat:@"Attemped to parse empty data for MIME Type '%@'", MIMEType];
|
||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errorMessage, NSLocalizedDescriptionKey, nil];
|
||||
*error = [NSError errorWithDomain:RKErrorDomain code:RKParserRegistryEmptyDataError userInfo:userInfo];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
id<RKParser> parser = [self parserForMIMEType:MIMEType];
|
||||
if (!parser) {
|
||||
if (error) {
|
||||
NSString* errorMessage = [NSString stringWithFormat:@"Cannot parse data without a parser for MIME Type '%@'", MIMEType];
|
||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errorMessage, NSLocalizedDescriptionKey, nil];
|
||||
*error = [NSError errorWithDomain:RKErrorDomain code:RKParserRegistryMissingParserError userInfo:userInfo];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [parser objectFromData:data error:error];
|
||||
}
|
||||
|
||||
- (id)parseData:(NSData *)data withMIMEType:(NSString *)MIMEType error:(NSError **)error {
|
||||
return [self parseData:data withMIMEType:MIMEType encoding:NSUTF8StringEncoding error:error];
|
||||
}
|
||||
|
||||
- (NSData *)serializeObject:(id)object forMIMEType:(NSString *)MIMEType error:(NSError **)error {
|
||||
id<RKParser> parser = [self parserForMIMEType:MIMEType];
|
||||
if (!parser) {
|
||||
if (error) {
|
||||
NSString* errorMessage = [NSString stringWithFormat:@"Cannot serialize object without a parser for MIME Type '%@'", MIMEType];
|
||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errorMessage, NSLocalizedDescriptionKey, nil];
|
||||
*error = [NSError errorWithDomain:RKErrorDomain code:RKParserRegistryMissingParserError userInfo:userInfo];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [parser dataFromObject:object error:error];
|
||||
}
|
||||
|
||||
- (Class<RKParser>)parserClassForMIMEType:(NSString *)MIMEType {
|
||||
id parserClass = [_MIMETypeToParserClasses objectForKey:MIMEType];
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
if (!parserClass)
|
||||
{
|
||||
for (NSArray *regexAndClass in _MIMETypeToParserClassesRegularExpressions) {
|
||||
NSRegularExpression *regex = [regexAndClass objectAtIndex:0];
|
||||
NSUInteger numberOfMatches = [regex numberOfMatchesInString:MIMEType options:0 range:NSMakeRange(0, [MIMEType length])];
|
||||
if (numberOfMatches) {
|
||||
parserClass = [regexAndClass objectAtIndex:1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return parserClass;
|
||||
}
|
||||
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMEType:(NSString *)MIMEType {
|
||||
[_MIMETypeToParserClasses setObject:parserClass forKey:MIMEType];
|
||||
}
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
|
||||
- (void)setParserClass:(Class<RKParser>)parserClass forMIMETypeRegularExpression:(NSRegularExpression *)MIMETypeRegex {
|
||||
NSArray *expressionAndClass = [NSArray arrayWithObjects:MIMETypeRegex, parserClass, nil];
|
||||
[_MIMETypeToParserClassesRegularExpressions addObject:expressionAndClass];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (id<RKParser>)parserForMIMEType:(NSString *)MIMEType {
|
||||
Class parserClass = [self parserClassForMIMEType:MIMEType];
|
||||
if (parserClass) {
|
||||
return [[parserClass alloc] init];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)canParseMIMEType:(NSString*)MIMEType {
|
||||
return [self parserClassForMIMEType:MIMEType] != nil;
|
||||
}
|
||||
|
||||
- (void)autoconfigure {
|
||||
Class parserClass = nil;
|
||||
|
||||
// JSON
|
||||
NSSet *JSONParserClassNames = [NSSet setWithObjects:@"RKJSONParserJSONKit", @"RKJSONParserYAJL", @"RKJSONParserSBJSON", @"RKJSONParserNXJSON", nil];
|
||||
for (NSString *parserClassName in JSONParserClassNames) {
|
||||
parserClass = NSClassFromString(parserClassName);
|
||||
if (parserClass) {
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeJSON];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// XML
|
||||
parserClass = NSClassFromString(@"RKXMLParserXMLReader");
|
||||
if (parserClass) {
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeXML];
|
||||
[self setParserClass:parserClass forMIMEType:RKMIMETypeTextXML];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user