Skip to content

Instantly share code, notes, and snippets.

@ambethia
Created February 5, 2010 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ambethia/295299 to your computer and use it in GitHub Desktop.
Save ambethia/295299 to your computer and use it in GitHub Desktop.
Category for TouchXML to convert a node to JSON. It won't provide fully valid JSON from any XML data, but it met my needs.
//
// CXMLNode+JSON.h
//
// Created by Jason L Perry on 1/24/10.
// Copyright 2010 Ambethia. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TouchXML.h"
@interface CXMLNode (JSON)
-(NSString *) toJSON;
-(NSString *) _toJSONWithAnonymity:(Boolean)anonymous;
@end
//
// CXMLNode+JSON.m
//
// Created by Jason L Perry on 1/24/10.
// Copyright 2010 Ambethia. All rights reserved.
//
#import "CXMLNode+JSON.h"
@implementation CXMLNode (JSON)
-(NSString *) toJSON {
return [self _toJSONWithAnonymity:YES];
}
-(NSString *) _toJSONWithAnonymity:(Boolean)anonymous {
NSMutableString *json = [[NSMutableString alloc] init];
if (!anonymous) {
[json appendFormat:@"%@: ", [self name]];
}
if ([[[self stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] > 0) {
[json appendFormat:@"\"%@\"", [self stringValue]];
} else {
NSMutableDictionary *childElements = [[NSMutableDictionary alloc] init];
for (CXMLNode *node in [self children]) {
if ([node kind] == CXMLElementKind) {
if ([childElements objectForKey:[node name]] == nil) {
NSMutableArray *nodes = [[NSMutableArray alloc] initWithObjects:node, nil];
[childElements setObject:nodes forKey:[node name]];
[nodes release];
} else {
[(NSMutableArray *)[childElements objectForKey:[node name]] addObject:node];
}
}
}
if ([childElements count] > 0) {
[json appendString:@"{ "];
NSMutableArray *childJson = [NSMutableArray arrayWithCapacity:[childElements count]];
for (id key in childElements) {
NSArray *elements = [childElements objectForKey:key];
if ([elements count] > 1) {
[json appendFormat:@"%@: ", key];
[json appendString:@"["];
NSMutableArray *arrayJson = [NSMutableArray arrayWithCapacity:[elements count]];
for (CXMLNode *node in elements) {
[arrayJson addObject:[node _toJSONWithAnonymity:YES]];
}
[json appendString:[arrayJson componentsJoinedByString:@", "]];
[json appendString:@"]"];
} else {
[childJson addObject:[[elements lastObject] _toJSONWithAnonymity:NO]];
}
}
[json appendString:[childJson componentsJoinedByString:@", "]];
[json appendString:@" }"];
} else {
[json appendString:@"null"];
}
[childElements release];
}
return [json autorelease];
}
@end
//
// CXMLNodeJSONTests.m
//
// Created by Jason L Perry on 1/24/10.
// Copyright 2010 Ambethia. All rights reserved.
//
// http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
//
#import <SenTestingKit/SenTestingKit.h>
#import "CXMLNode+JSON.h"
@interface CXMLNodeJSONTests : SenTestCase {
}
- (NSString *) getJSON:(NSString *)json fromXML:(NSString *)xml;
@end
@implementation CXMLNodeJSONTests
- (void) testPatternTwo {
NSString *xml = @"<e>text</e>";
NSString *json = @"\"text\"";
STAssertEqualObjects([self getJSON:json fromXML:xml], json, @"Pattern 2 Failure");
}
- (void) testPatternFive {
NSString *xml = @"<e> <a>text</a> <b>text</b> </e>";
NSString *json = @"{ a: \"text\", b: \"text\" }";
STAssertEqualObjects([self getJSON:json fromXML:xml], json, @"Pattern 5 Failure");
}
- (void) testPatternSix {
NSString *xml = @"<e> <a>text</a> <a>text</a> </e>";
NSString *json = @"{ a: [\"text\", \"text\"] }";
STAssertEqualObjects([self getJSON:json fromXML:xml], json, @"Pattern 6 Failure");
}
- (void) testPatternOneKinda {
NSString *xml = @"<e> <a></a> </e>";
NSString *json = @"{ a: null }";
STAssertEqualObjects([self getJSON:json fromXML:xml], json, @"Pattern 1 Failure");
}
- (NSString *) getJSON:(NSString *)json fromXML:(NSString *)xml {
CXMLDocument *parser = [[CXMLDocument alloc] initWithXMLString:xml options:0 error:nil];
CXMLElement *e = [[parser nodesForXPath:@"//e" error:nil] lastObject];
NSString *res = [e toJSON];
[parser release];
return res;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment