Skip to content

Commit bcf6bd7

Browse files
committed
Merge pull request jsonmodel#243 from Johnykutty/master
Redundant data < - > string conversion avoided
2 parents cb74741 + bef8d57 commit bcf6bd7

File tree

4 files changed

+168
-18
lines changed

4 files changed

+168
-18
lines changed

JSONModel/JSONModel/JSONModel.m

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,24 @@ -(id)init
114114

115115
-(instancetype)initWithData:(NSData *)data error:(NSError *__autoreleasing *)err
116116
{
117-
//turn nsdata to an nsstring
118-
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
119-
if (!string) return nil;
120-
121-
//create an instance
117+
//check for nil input
118+
if (!data) {
119+
if (err) *err = [JSONModelError errorInputIsNil];
120+
return nil;
121+
}
122+
//read the json
122123
JSONModelError* initError = nil;
123-
id objModel = [self initWithString:string usingEncoding:NSUTF8StringEncoding error:&initError];
124+
id obj = [NSJSONSerialization JSONObjectWithData:data
125+
options:kNilOptions
126+
error:&initError];
127+
128+
if (initError) {
129+
if (err) *err = [JSONModelError errorBadJSON];
130+
return nil;
131+
}
132+
133+
//init with dictionary
134+
id objModel = [self initWithDictionary:obj error:&initError];
124135
if (initError && err) *err = initError;
125136
return objModel;
126137
}
@@ -141,21 +152,11 @@ -(id)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding
141152
return nil;
142153
}
143154

144-
//read the json
145155
JSONModelError* initError = nil;
146-
id obj = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:encoding]
147-
options:kNilOptions
148-
error:&initError];
149-
150-
if (initError) {
151-
if (err) *err = [JSONModelError errorBadJSON];
152-
return nil;
153-
}
154-
155-
//init with dictionary
156-
id objModel = [self initWithDictionary:obj error:&initError];
156+
id objModel = [self initWithData:[string dataUsingEncoding:encoding] error:&initError];
157157
if (initError && err) *err = initError;
158158
return objModel;
159+
159160
}
160161

161162
-(id)initWithDictionary:(NSDictionary*)dict error:(NSError**)err
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//
2+
// InitWithDataTests.m
3+
// JSONModelDemo_iOS
4+
//
5+
// Created by Johnykutty on 14/09/14.
6+
// Copyright (c) 2014 Underplot ltd. All rights reserved.
7+
//
8+
9+
#import <XCTest/XCTest.h>
10+
#import "PrimitivesModel.h"
11+
#import "NestedModel.h"
12+
#import "CopyrightModel.h"
13+
14+
@interface InitWithDataTests : XCTestCase
15+
16+
@end
17+
18+
@implementation InitWithDataTests
19+
20+
- (void)setUp
21+
{
22+
[super setUp];
23+
// Put setup code here. This method is called before the invocation of each test method in the class.
24+
}
25+
26+
- (void)tearDown
27+
{
28+
// Put teardown code here. This method is called after the invocation of each test method in the class.
29+
[super tearDown];
30+
}
31+
32+
-(void)testForNilInputFromData
33+
{
34+
JSONModelError* err = nil;
35+
36+
//test for nil string input
37+
CopyrightModel* cpModel = [[CopyrightModel alloc] initWithData:nil
38+
error:&err];
39+
cpModel=nil;
40+
41+
XCTAssertTrue(err!=nil, @"No error returned when initialized with nil string");
42+
XCTAssertTrue(err.code == kJSONModelErrorNilInput, @"Wrong error for nil string input");
43+
}
44+
45+
-(void)testErrorsInNestedModelsArray
46+
{
47+
NSError* err = [self performTestErrorsInNestedModelFile:@"nestedDataWithArrayError.json"];
48+
49+
// Make sure that the error is at the expected key-path
50+
XCTAssertEqualObjects(err.userInfo[kJSONModelKeyPath], @"images[1]", @"kJSONModelKeyPath does not contain the expected path of the error.");
51+
}
52+
53+
-(void)testErrorsInNestedModelsDictionary
54+
{
55+
NSError* err = [self performTestErrorsInNestedModelFile:@"nestedDataWithDictionaryError.json"];
56+
57+
// Make sure that the error is at the expected key-path
58+
XCTAssertEqualObjects(err.userInfo[kJSONModelKeyPath], @"imagesObject.image2", @"kJSONModelKeyPath does not contain the expected path of the error.");
59+
}
60+
61+
- (NSError*)performTestErrorsInNestedModelFile:(NSString*)jsonFilename
62+
{
63+
NSString* filePath = [[NSBundle bundleForClass:[JSONModel class]].resourcePath stringByAppendingPathComponent:jsonFilename];
64+
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
65+
66+
XCTAssertNotNil(jsonData, @"Can't fetch test data file contents.");
67+
68+
NSError* err = nil;
69+
NestedModel* n = [[NestedModel alloc] initWithData: jsonData error:&err];
70+
XCTAssertNotNil(err, @"No error thrown when loading invalid data");
71+
72+
XCTAssertNil(n, @"Model is not nil, when invalid data input");
73+
XCTAssertTrue(err.code == kJSONModelErrorInvalidData, @"Wrong error for missing keys");
74+
75+
// Make sure that 'name' is listed as the missing key
76+
XCTAssertEqualObjects(err.userInfo[kJSONModelMissingKeys][0], @"name", @"'name' should be the missing key.");
77+
return err;
78+
}
79+
80+
-(void)testMissingKeysError
81+
{
82+
NSString* filePath = [[NSBundle bundleForClass:[JSONModel class]].resourcePath stringByAppendingPathComponent:@"primitivesWithErrors.json"];
83+
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
84+
85+
XCTAssertNotNil(jsonData, @"Can't fetch test data file contents.");
86+
87+
NSError* err;
88+
PrimitivesModel* p = [[PrimitivesModel alloc] initWithData: jsonData error:&err];
89+
XCTAssertNil(p, @"Model is not nil, when input is invalid");
90+
XCTAssertNotNil(err, @"No error when keys are missing.");
91+
92+
XCTAssertTrue(err.code == kJSONModelErrorInvalidData, @"Wrong error for missing keys");
93+
NSArray* missingKeys = err.userInfo[kJSONModelMissingKeys];
94+
missingKeys = [missingKeys sortedArrayUsingSelector:@selector(compare:)];
95+
XCTAssertTrue(missingKeys, @"error does not have kJSONModelMissingKeys keys in user info");
96+
XCTAssertTrue([missingKeys[0] isEqualToString:@"intNumber"],@"missing field intNumber not found in missingKeys");
97+
XCTAssertTrue([missingKeys[1] isEqualToString:@"longNumber"],@"missing field longNumber not found in missingKeys");
98+
}
99+
100+
-(void)testTypeMismatchErrorImages
101+
{
102+
NSString* filePath = [[NSBundle bundleForClass:[JSONModel class]].resourcePath stringByAppendingPathComponent:@"nestedDataWithTypeMismatchOnImages.json"];
103+
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
104+
105+
XCTAssertNotNil(jsonData, @"Can't fetch test data file contents.");
106+
107+
NSError* err = nil;
108+
NestedModel* p = [[NestedModel alloc] initWithData: jsonData error:&err];
109+
XCTAssertNil(p, @"Model is not nil, when input is invalid");
110+
XCTAssertNotNil(err, @"No error when types mismatch.");
111+
112+
XCTAssertTrue(err.code == kJSONModelErrorInvalidData, @"Wrong error for type mismatch");
113+
NSString* mismatchDescription = err.userInfo[kJSONModelTypeMismatch];
114+
XCTAssertTrue(mismatchDescription, @"error does not have kJSONModelTypeMismatch key in user info");
115+
XCTAssertTrue([mismatchDescription rangeOfString:@"'images'"].location != NSNotFound, @"error should mention that the 'images' property (expecting an Array) is mismatched.");
116+
117+
// Make sure that the error is at the expected key-path
118+
XCTAssertEqualObjects(err.userInfo[kJSONModelKeyPath], @"images", @"kJSONModelKeyPath does not contain the expected path of the error.");
119+
}
120+
121+
-(void)testTypeMismatchErrorImagesObject
122+
{
123+
NSString* filePath = [[NSBundle bundleForClass:[JSONModel class]].resourcePath stringByAppendingPathComponent:@"nestedDataWithTypeMismatchOnImagesObject.json"];
124+
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
125+
126+
XCTAssertNotNil(jsonData, @"Can't fetch test data file contents.");
127+
128+
NSError* err;
129+
NestedModel* p = [[NestedModel alloc] initWithData: jsonData error:&err];
130+
XCTAssertNil(p, @"Model is not nil, when input is invalid");
131+
XCTAssertNotNil(err, @"No error when types mismatch.");
132+
133+
XCTAssertTrue(err.code == kJSONModelErrorInvalidData, @"Wrong error for type mismatch");
134+
NSString* mismatchDescription = err.userInfo[kJSONModelTypeMismatch];
135+
XCTAssertTrue(mismatchDescription, @"error does not have kJSONModelTypeMismatch key in user info");
136+
XCTAssertTrue([mismatchDescription rangeOfString:@"'imagesObject'"].location != NSNotFound, @"error should mention that the 'imagesObject' property (expecting a Dictionary) is mismatched.");
137+
138+
// Make sure that the error is at the expected key-path
139+
XCTAssertEqualObjects(err.userInfo[kJSONModelKeyPath], @"imagesObject", @"kJSONModelKeyPath does not contain the expected path of the error.");
140+
}
141+
142+
@end

JSONModelDemo_iOS.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
4A50001D19C5DCCF00C161A0 /* InitWithDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A50001C19C5DCCF00C161A0 /* InitWithDataTests.m */; };
1011
69286BDA17FA280900D1BA81 /* nestedDataWithDictionaryError.json in Resources */ = {isa = PBXBuildFile; fileRef = 69286BD917FA280900D1BA81 /* nestedDataWithDictionaryError.json */; };
1112
69286BDB17FA280900D1BA81 /* nestedDataWithDictionaryError.json in Resources */ = {isa = PBXBuildFile; fileRef = 69286BD917FA280900D1BA81 /* nestedDataWithDictionaryError.json */; };
1213
697852FD17D934B5006BFCD0 /* nestedDataWithTypeMismatchOnImages.json in Resources */ = {isa = PBXBuildFile; fileRef = 697852FC17D934B5006BFCD0 /* nestedDataWithTypeMismatchOnImages.json */; };
@@ -151,6 +152,7 @@
151152
/* End PBXContainerItemProxy section */
152153

153154
/* Begin PBXFileReference section */
155+
4A50001C19C5DCCF00C161A0 /* InitWithDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InitWithDataTests.m; sourceTree = "<group>"; };
154156
69286BD917FA280900D1BA81 /* nestedDataWithDictionaryError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nestedDataWithDictionaryError.json; sourceTree = "<group>"; };
155157
697852FC17D934B5006BFCD0 /* nestedDataWithTypeMismatchOnImages.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nestedDataWithTypeMismatchOnImages.json; sourceTree = "<group>"; };
156158
697852FE17D93546006BFCD0 /* nestedDataWithTypeMismatchOnImagesObject.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nestedDataWithTypeMismatchOnImagesObject.json; sourceTree = "<group>"; };
@@ -419,6 +421,7 @@
419421
9C735D6E170C007900FF96F5 /* InitFromWebTests.h */,
420422
9C735D6F170C007900FF96F5 /* InitFromWebTests.m */,
421423
9CCAFD911901B44300314886 /* SpecialPropertiesTests.m */,
424+
4A50001C19C5DCCF00C161A0 /* InitWithDataTests.m */,
422425
);
423426
path = UnitTests;
424427
sourceTree = "<group>";
@@ -948,6 +951,7 @@
948951
9C66E035168CF0AA0015CCDF /* JSONKeyMapper.m in Sources */,
949952
9C66E037168CF0AA0015CCDF /* JSONValueTransformer.m in Sources */,
950953
9CB1EE42172C1136004BAA07 /* SpecialPropertyNameTests.m in Sources */,
954+
4A50001D19C5DCCF00C161A0 /* InitWithDataTests.m in Sources */,
951955
9CD425751701FE0000A42AA1 /* HTTPClientSuite.m in Sources */,
952956
9CD425781701FF2100A42AA1 /* MTTestSemaphor.m in Sources */,
953957
9CD4257B1702002900A42AA1 /* MockNSURLConnection.m in Sources */,

JSONModelDemo_iOS/MasterViewController.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ -(void)viewDidAppear:(BOOL)animated
122122
TopModel* tm = [[TopModel alloc] initWithString:json error:nil];
123123
NSLog(@"tm: %@", tm.toDictionary);
124124
NSLog(@"to string: %@", tm.toJSONString);
125+
tm = [[TopModel alloc] initWithData:[json dataUsingEncoding:NSUTF8StringEncoding] error:nil];
126+
NSLog(@"tm - WithData : %@", tm.toDictionary);
127+
NSLog(@"to string - WithData : %@", tm.toJSONString);
125128
}
126129

127130
-(IBAction)actionLoadCall:(id)sender

0 commit comments

Comments
 (0)