Skip to content
Browse files

Document SBJsonStreamParserAdapter & rename -skip to -levelsToSkip

  • Loading branch information...
1 parent bac71bf commit 6fccd1f547aa02ae5beff0488e66bfc6b6aff914 @stig stig committed Jun 4, 2011
Showing with 77 additions and 18 deletions.
  1. +70 −11 Classes/SBJsonStreamParserAdapter.h
  2. +5 −5 Classes/SBJsonStreamParserAdapter.m
  3. +2 −2 Tests/StreamParserIntegrationTest.m
View
81 Classes/SBJsonStreamParserAdapter.h
@@ -42,25 +42,82 @@ typedef enum {
/**
@brief Delegate for getting objects & arrays from the stream parser adapter
- You will most likely find it much more convenient to implement this
- than the raw SBJsonStreamParserDelegate protocol.
-
- @see The TwitterStream example project.
+ @see The TweetStream example project.
*/
@protocol SBJsonStreamParserAdapterDelegate
-/// Called when a JSON array is found
+/**
+ @brief Called if a JSON array is found
+
+ This method is called if a JSON array is found.
+
+ */
- (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray*)array;
-/// Called when a JSON object is found
+/**
+ @brief Called when a JSON object is found
+
+ This method is called if a JSON object is found.
+ */
- (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary*)dict;
@end
+/**
+ @brief SBJsonStreamParserDelegate protocol adapter
+
+ Rather than implementing the SBJsonStreamParserDelegate protocol yourself you will
+ most likely find it much more convenient to use an instance of this class and
+ implement the SBJsonStreamParserAdapterDelegate protocol instead.
+
+ Normally you would only get one call from either the -parser:foundArray: or
+ -parser:foundObject: method. However, if your inputs contains multiple JSON
+ documents and you set the parser's -supportMultipleDocuments property to YES
+ you will get one call for each full method.
+
+ @code
+ SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];
+ adapter.delegate = self;
+
+ SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];
+ parser.delegate = adapter;
+ parser.supportMultipleDocuments = YES;
+
+ // Note that this input contains multiple top-level JSON documents
+ NSData *json = [@"[]{}[]{}" dataWithEncoding:NSUTF8StringEncoding];
+ [parser parse:data];
+ @endcode
+
+ In the above example @p self will have the following sequence of methods called on it:
+
+ @li -parser:foundArray:
+ @li -parser:foundObject:
+ @li -parser:foundArray:
+ @li -parser:foundObject:
+ Often you won't have control over the input you're parsing, so can't make use of
+ this feature. But, all is not lost: this class will let you get the same effect by
+ allowing you to skip one or more of the outer enclosing objects. Thus, the next
+ example results in the same sequence of -parser:foundArray: / -parser:foundObject:
+ being called on your delegate.
+
+ @code
+ SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];
+ adapter.delegate = self;
+ adapter.levelsToSkip = 1;
+
+ SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];
+ parser.delegate = adapter;
+
+ // Note that this input contains A SINGLE top-level document
+ NSData *json = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding];
+ [parser parse:data];
+ @endcode
+
+*/
@interface SBJsonStreamParserAdapter : NSObject <SBJsonStreamParserDelegate> {
id<SBJsonStreamParserAdapterDelegate> delegate;
- NSUInteger skip, depth;
+ NSUInteger levelsToSkip, depth;
__weak NSMutableArray *array;
__weak NSMutableDictionary *dict;
NSMutableArray *keyStack;
@@ -72,17 +129,19 @@ typedef enum {
/**
@brief How many levels to skip
- This is useful for parsing HUGE JSON documents, particularly if it consists of an
- outer array and multiple objects.
+ This is useful for parsing huge JSON documents, or documents coming in over a very slow link.
If you set this to N it will skip the outer N levels and call the -parser:foundArray:
or -parser:foundObject: methods for each of the inner objects, as appropriate.
@see The StreamParserIntegrationTest.m file for examples
*/
-@property NSUInteger skip;
+@property NSUInteger levelsToSkip;
-/// Set this to the object you want to receive messages
+/**
+ @brief Your delegate object
+ Set this to the object you want to receive the SBJsonStreamParserAdapterDelegate messages.
+ */
@property (assign) id<SBJsonStreamParserAdapterDelegate> delegate;
@end
View
10 Classes/SBJsonStreamParserAdapter.m
@@ -44,7 +44,7 @@ - (void)parser:(SBJsonStreamParser*)parser found:(id)obj;
@implementation SBJsonStreamParserAdapter
@synthesize delegate;
-@synthesize skip;
+@synthesize levelsToSkip;
#pragma mark Housekeeping
@@ -115,7 +115,7 @@ - (void)parser:(SBJsonStreamParser*)parser found:(id)obj {
#pragma mark Delegate methods
- (void)parserFoundObjectStart:(SBJsonStreamParser*)parser {
- if (++depth > skip) {
+ if (++depth > levelsToSkip) {
dict = [[NSMutableDictionary new] autorelease];
[stack addObject:dict];
currentType = SBJsonStreamParserAdapterObject;
@@ -127,7 +127,7 @@ - (void)parser:(SBJsonStreamParser*)parser foundObjectKey:(NSString*)key_ {
}
- (void)parserFoundObjectEnd:(SBJsonStreamParser*)parser {
- if (depth-- > skip) {
+ if (depth-- > levelsToSkip) {
id value = [dict retain];
[self pop];
[self parser:parser found:value];
@@ -136,15 +136,15 @@ - (void)parserFoundObjectEnd:(SBJsonStreamParser*)parser {
}
- (void)parserFoundArrayStart:(SBJsonStreamParser*)parser {
- if (++depth > skip) {
+ if (++depth > levelsToSkip) {
array = [[NSMutableArray new] autorelease];
[stack addObject:array];
currentType = SBJsonStreamParserAdapterArray;
}
}
- (void)parserFoundArrayEnd:(SBJsonStreamParser*)parser {
- if (depth-- > skip) {
+ if (depth-- > levelsToSkip) {
id value = [array retain];
[self pop];
[self parser:parser found:value];
View
4 Tests/StreamParserIntegrationTest.m
@@ -108,14 +108,14 @@ - (void)testSingleArray {
}
- (void)testSkipArray {
- adapter.skip = 1;
+ adapter.levelsToSkip = 1;
[self parseArrayOfObjects];
STAssertEquals(arrayCount, (NSUInteger)0, nil);
STAssertEquals(objectCount, (NSUInteger)100, nil);
}
- (void)testSkipArrayAndObject {
- adapter.skip = 2;
+ adapter.levelsToSkip = 2;
[self parseArrayOfObjects];
STAssertEquals(arrayCount, (NSUInteger)200, nil);
STAssertEquals(objectCount, (NSUInteger)0, nil);

0 comments on commit 6fccd1f

Please sign in to comment.
Something went wrong with that request. Please try again.