Of all the JSON parsing libraries for the iPhone, the one I like the most is YAJL-obj, which is based on the “event driven/SAX style” YAJL. When I first started creating iPhone applications, I used a lot of Plists; I’ve now switched this all over to JSON not only because it’s more standards-y, but also because I can use the same data sets with my Python/Django and Android applications.
The JSON data I’m working with looks something like a dump of a SQL Table: lots of rows using the same column names — i.e. dictionary keys – over and over. If you’re loading a couple of thousand rows of data, each with 20 or or 30 columns/keys, the shear size of the key strings can add up — even though really there’s only a couple of dozen keys in total really in use. All these duplications waste a lot of memory – which is especially tight on a 8Gb iPod Touch – so I decided it might help out to actually reuse keys in my JSON loaders.
Here’s the changes I made to YAJL:
YAJLDocument.h
@interface YAJLDocument : NSObject {
...
NSMutableDictionary *keyStore_;
}
@property(nonatomic,retain) NSMutableDictionary *keyStore_;
YAJLDocument.m
- (id)initWithParserOptions:(YAJLParserOptions)parserOptions {
if ((self = [super init])) {
...
keyStore_ = [[NSMutableDictionary alloc] initWithCapacity:16];
}
return self;
}
- (void)parser:(YAJLParser *)parser didMapKey:(NSString *)key {
#if 1 // DPJ 2010-03-01
key_ = [keyStore_ objectForKey:key];
if (!key_) {
[keyStore_ setObject:key forKey:key];
key_ = key;
}
#else
key_ = key;
#endif
[keyStack_ addObject:key_]; // Push
}
To rebuild your library:
- select build target Device – 3.0 | Release | Combine Libs
- the output file is
Project-IPhone/build/libYAJLIPhone-*.zip - just add all the things in that ZIP file to your iPhone project and you’re good to go
Final thoughts:
- whether this happens or not should be controlled by the YAJLParserOptions
- I’m probably going keep modifying this code, adding a version with a “scrubbing delegate” that allows dictionaries to be scrubbed on the spot of data not needed in the application
I wonder if having a category on NSString for this would be more useful?
Then you could just do something like:
key_ = [key internedString];
to get the canonical copy of the key. And you could use it anywhere you thought you might have duplicate strings.
Later,
Blake.
It’s an excellent idea, but since I’m compiling this in a library and have to make sure I reduce the external dependencies, I think.