Skip to content

Commit 405bbec

Browse files
committed
Roll SBJsonStreamParserAdapter into SBJsonStreamParser. Fixes SBJson#83.
1 parent 15fe45f commit 405bbec

13 files changed

+217
-444
lines changed

Classes/SBJson.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
#import "SBJsonParser.h"
7979
#import "SBJsonWriter.h"
8080
#import "SBJsonStreamParser.h"
81-
#import "SBJsonStreamParserAdapter.h"
8281
#import "SBJsonStreamWriter.h"
8382
#import "NSObject+SBJson.h"
8483

Classes/SBJsonParser.m

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929

3030
#import "SBJsonParser.h"
3131
#import "SBJsonStreamParser.h"
32-
#import "SBJsonStreamParserAdapter.h"
3332
#import "SBJsonStreamParserAccumulator.h"
3433

3534
@implementation SBJsonParser
@@ -60,12 +59,9 @@ - (id)objectWithData:(NSData *)data {
6059

6160
SBJsonStreamParserAccumulator *accumulator = [[[SBJsonStreamParserAccumulator alloc] init] autorelease];
6261

63-
SBJsonStreamParserAdapter *adapter = [[[SBJsonStreamParserAdapter alloc] init] autorelease];
64-
adapter.delegate = accumulator;
65-
6662
SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];
6763
parser.maxDepth = self.maxDepth;
68-
parser.delegate = adapter;
64+
parser.delegate = accumulator;
6965

7066
switch ([parser parse:data]) {
7167
case SBJsonStreamParserComplete:

Classes/SBJsonStreamParser.h

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -44,67 +44,116 @@ typedef enum {
4444

4545

4646
/**
47-
@brief Delegate for interacting directly with the stream parser
48-
49-
You will most likely find it much more convenient to implement the
50-
SBJsonStreamParserAdapterDelegate protocol instead.
47+
@brief SBJsonStreamParserDelegate protocol adapter
48+
49+
@see SBJsonStreamParser
5150
*/
5251
@protocol SBJsonStreamParserDelegate
5352

54-
/// Called when object start is found
55-
- (void)parserFoundObjectStart:(SBJsonStreamParser*)parser;
56-
57-
/// Called when object key is found
58-
- (void)parser:(SBJsonStreamParser*)parser foundObjectKey:(NSString*)key;
59-
60-
/// Called when object end is found
61-
- (void)parserFoundObjectEnd:(SBJsonStreamParser*)parser;
62-
63-
/// Called when array start is found
64-
- (void)parserFoundArrayStart:(SBJsonStreamParser*)parser;
65-
66-
/// Called when array end is found
67-
- (void)parserFoundArrayEnd:(SBJsonStreamParser*)parser;
68-
69-
/// Called when a boolean value is found
70-
- (void)parser:(SBJsonStreamParser*)parser foundBoolean:(BOOL)x;
71-
72-
/// Called when a null value is found
73-
- (void)parserFoundNull:(SBJsonStreamParser*)parser;
74-
75-
/// Called when a number is found
76-
- (void)parser:(SBJsonStreamParser*)parser foundNumber:(NSNumber*)num;
53+
/**
54+
@brief Called if a JSON array is found
55+
56+
This method is called if a JSON array is found.
57+
58+
*/
59+
- (void)parser:(SBJsonStreamParser*)parser foundArray:(NSArray*)array;
7760

78-
/// Called when a string is found
79-
- (void)parser:(SBJsonStreamParser*)parser foundString:(NSString*)string;
61+
/**
62+
@brief Called when a JSON object is found
63+
64+
This method is called if a JSON object is found.
65+
*/
66+
- (void)parser:(SBJsonStreamParser*)parser foundObject:(NSDictionary*)dict;
8067

8168
@end
8269

70+
typedef enum {
71+
SBJsonStreamParserNone,
72+
SBJsonStreamParserArray,
73+
SBJsonStreamParserObject,
74+
} SBJsonStreamParserType;
8375

8476
/**
8577
@brief Parse a stream of JSON data.
8678
8779
Using this class directly you can reduce the apparent latency for each
8880
download/parse cycle of documents over a slow connection. You can start
8981
parsing *and return chunks of the parsed document* before the entire
90-
document is downloaded.
82+
document is downloaded. Using this class is also useful to parse huge
83+
documents on disk bit by bit so you don't have to keep them all in memory.
84+
85+
The default behaviour is that the delegate only receives one call from
86+
either the -parser:foundArray: or -parser:foundObject: method when the
87+
document is fully parsed. However, if your inputs contains multiple JSON
88+
documents and you set the parser's -supportMultipleDocuments property to YES
89+
you will get one call for each full method.
90+
91+
@code
92+
SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];
93+
parser.delegate = self;
94+
parser.supportMultipleDocuments = YES;
95+
96+
// Note that this input contains multiple top-level JSON documents
97+
NSData *json = [@"[]{}[]{}" dataWithEncoding:NSUTF8StringEncoding];
98+
[parser parse:data];
99+
@endcode
91100
92-
Using this class is also useful to parse huge documents on disk
93-
bit by bit so you don't have to keep them all in memory.
101+
In the above example @p self will have the following sequence of methods called on it:
94102
95-
@see SBJsonStreamParserAdapter for more information.
103+
@li -parser:foundArray:
104+
@li -parser:foundObject:
105+
@li -parser:foundArray:
106+
@li -parser:foundObject:
96107
108+
Often you won't have control over the input you're parsing, so can't make use of
109+
this feature. But, all is not lost: this class will let you get the same effect by
110+
allowing you to skip one or more of the outer enclosing objects. Thus, the next
111+
example results in the same sequence of -parser:foundArray: / -parser:foundObject:
112+
being called on your delegate.
113+
114+
@code
115+
SBJsonStreamParser *parser = [[[SBJsonStreamParser alloc] init] autorelease];
116+
parser.delegate = self;
117+
parser.levelsToSkip = 1;
118+
119+
// Note that this input contains A SINGLE top-level document
120+
NSData *json = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding];
121+
[parser parse:data];
122+
@endcode
123+
124+
@see SBJsonStreamParserDelegate
97125
@see @ref objc2json
98126
99127
*/
100128
@interface SBJsonStreamParser : NSObject {
101129
@private
102130
SBJsonTokeniser *tokeniser;
131+
132+
NSUInteger depth;
133+
NSMutableArray *array;
134+
NSMutableDictionary *dict;
135+
NSMutableArray *keyStack;
136+
NSMutableArray *stack;
137+
138+
SBJsonStreamParserType currentType;
103139
}
104140

105141
@property (nonatomic, assign) SBJsonStreamParserState *state; // Private
106142
@property (nonatomic, readonly, retain) NSMutableArray *stateStack; // Private
107143

144+
145+
/**
146+
@brief How many levels to skip
147+
148+
This is useful for parsing huge JSON documents, or documents coming in over a very slow link.
149+
150+
If you set this to N it will skip the outer N levels and call the -parser:foundArray:
151+
or -parser:foundObject: methods for each of the inner objects, as appropriate.
152+
153+
@see The StreamParserIntegrationTest.m file for examples
154+
*/
155+
@property NSUInteger levelsToSkip;
156+
108157
/**
109158
@brief Expect multiple documents separated by whitespace
110159
@@ -126,7 +175,7 @@ typedef enum {
126175
into valid tokens.
127176
128177
@note
129-
Usually this should be an instance of SBJsonStreamParserAdapter, but you can
178+
Usually this should be an instance of SBJsonStreamParser, but you can
130179
substitute your own implementation of the SBJsonStreamParserDelegate protocol if you need to.
131180
*/
132181
@property (assign) id<SBJsonStreamParserDelegate> delegate;

0 commit comments

Comments
 (0)