Skip to content

Commit ca2b9f2

Browse files
committed
Boost speed for JSON->model conversion process.(#837 #835 #834)
1 parent 69a5a90 commit ca2b9f2

26 files changed

+703
-112
lines changed

Diff for: MJExtension.xcodeproj/project.pbxproj

+18-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
0130EE80233C56D8008D2386 /* MJFrenchUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 0130EE7F233C56D8008D2386 /* MJFrenchUser.m */; };
2222
0179886C24EFA460007F7FBC /* MJTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0179886B24EFA460007F7FBC /* MJTester.swift */; };
2323
0179887024EFA58B007F7FBC /* SwiftModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */; };
24-
01BC91E2277418DF004E5265 /* ValueTransformingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */; };
24+
01BB00FD277EC1FF002EF5B3 /* DeprecatedAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */; };
25+
01BB0100277EE8DC002EF5B3 /* NSDate+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; };
26+
01BB0101277EE8DC002EF5B3 /* NSDate+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */; };
27+
01BC91E2277418DF004E5265 /* ValueTransformingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */; };
2528
01BC91E427741956004E5265 /* MJCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E327741956004E5265 /* MJCredential.swift */; };
2629
01BC91E627741D8C004E5265 /* MJArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E527741D8C004E5265 /* MJArticle.swift */; };
2730
01BC921327747C06004E5265 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC920B27747C05004E5265 /* Benchmark.swift */; };
@@ -95,7 +98,10 @@
9598
0179886A24EFA460007F7FBC /* MJExtensionTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MJExtensionTests-Bridging-Header.h"; sourceTree = "<group>"; };
9699
0179886B24EFA460007F7FBC /* MJTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJTester.swift; sourceTree = "<group>"; };
97100
0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftModelTests.swift; sourceTree = "<group>"; };
98-
01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValueTransformingTest.swift; sourceTree = "<group>"; };
101+
01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeprecatedAPITests.swift; sourceTree = "<group>"; };
102+
01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+MJExtension.h"; sourceTree = "<group>"; };
103+
01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+MJExtension.m"; sourceTree = "<group>"; };
104+
01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValueTransformingTests.swift; sourceTree = "<group>"; };
99105
01BC91E327741956004E5265 /* MJCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJCredential.swift; sourceTree = "<group>"; };
100106
01BC91E527741D8C004E5265 /* MJArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJArticle.swift; sourceTree = "<group>"; };
101107
01BC920B27747C05004E5265 /* Benchmark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Benchmark.swift; sourceTree = "<group>"; };
@@ -268,6 +274,8 @@
268274
2D2DBA062317DB32005A689E /* NSObject+MJKeyValue.m */,
269275
2D2DBA142317DB33005A689E /* NSString+MJExtension.h */,
270276
2D2DBA0B2317DB32005A689E /* NSString+MJExtension.mm */,
277+
01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */,
278+
01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */,
271279
2D2DB9F62317DA64005A689E /* MJExtension.h */,
272280
2D2DB9F72317DA64005A689E /* Info.plist */,
273281
);
@@ -283,11 +291,12 @@
283291
0107507526E88DA600AAEA10 /* CoreDataModel */,
284292
2D2DBA5F2317DBDF005A689E /* Model */,
285293
2D2DBA572317DBB9005A689E /* MJExtensionTests.m */,
286-
01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */,
294+
01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */,
287295
010DF01D2761D90A0007EEF0 /* SpecialPropertyTypeTests.swift */,
288296
0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */,
289297
01052EAC25F872D00049EC6F /* MultiThreadTests.swift */,
290298
0107507D26E890C100AAEA10 /* CoreDataTests.swift */,
299+
01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */,
291300
01BC920B27747C05004E5265 /* Benchmark.swift */,
292301
2D2DBA592317DBB9005A689E /* Info.plist */,
293302
2D2DBA872317DCCF005A689E /* PrefixHeader.pch */,
@@ -345,6 +354,7 @@
345354
2D2DBA262317DB33005A689E /* MJProperty.h in Headers */,
346355
2D2DBA252317DB33005A689E /* MJPropertyKey.h in Headers */,
347356
01F5515E2757144500518218 /* MJEClass.h in Headers */,
357+
01BB0100277EE8DC002EF5B3 /* NSDate+MJExtension.h in Headers */,
348358
2D2DB9F82317DA64005A689E /* MJExtension.h in Headers */,
349359
2D2DBA222317DB33005A689E /* MJFoundation.h in Headers */,
350360
);
@@ -538,6 +548,7 @@
538548
2D2DBA1A2317DB33005A689E /* NSObject+MJKeyValue.m in Sources */,
539549
2D2DBA192317DB33005A689E /* MJPropertyKey.m in Sources */,
540550
2D2DBA202317DB33005A689E /* MJFoundation.m in Sources */,
551+
01BB0101277EE8DC002EF5B3 /* NSDate+MJExtension.m in Sources */,
541552
);
542553
runOnlyForDeploymentPostprocessing = 0;
543554
};
@@ -560,12 +571,13 @@
560571
2D2DBA852317DBE0005A689E /* MJPerson.m in Sources */,
561572
01BC921327747C06004E5265 /* Benchmark.swift in Sources */,
562573
0107507C26E88EAC00AAEA10 /* MJCoreDataTester+CoreDataProperties.swift in Sources */,
563-
01BC91E2277418DF004E5265 /* ValueTransformingTest.swift in Sources */,
574+
01BC91E2277418DF004E5265 /* ValueTransformingTests.swift in Sources */,
564575
2D2DBA7B2317DBE0005A689E /* MJBox.m in Sources */,
565576
2D2DBA582317DBB9005A689E /* MJExtensionTests.m in Sources */,
566577
010DF01E2761D90A0007EEF0 /* SpecialPropertyTypeTests.swift in Sources */,
567578
2D2DBA7E2317DBE0005A689E /* MJBag.m in Sources */,
568579
2D2DBA7F2317DBE0005A689E /* MJBaseObject.m in Sources */,
580+
01BB00FD277EC1FF002EF5B3 /* DeprecatedAPITests.swift in Sources */,
569581
2D2DBA7D2317DBE0005A689E /* MJBook.m in Sources */,
570582
0107507E26E890C100AAEA10 /* CoreDataTests.swift in Sources */,
571583
0107507826E88DD400AAEA10 /* MJCoreDataTestModel.xcdatamodeld in Sources */,
@@ -682,6 +694,7 @@
682694
isa = XCBuildConfiguration;
683695
buildSettings = {
684696
ALWAYS_SEARCH_USER_PATHS = NO;
697+
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
685698
CLANG_ANALYZER_NONNULL = YES;
686699
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
687700
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@@ -742,6 +755,7 @@
742755
isa = XCBuildConfiguration;
743756
buildSettings = {
744757
ALWAYS_SEARCH_USER_PATHS = NO;
758+
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
745759
CLANG_ANALYZER_NONNULL = YES;
746760
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
747761
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";

Diff for: MJExtension/MJEClass.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ NS_ASSUME_NONNULL_BEGIN
2121
BOOL _hasOld2NewModifier;
2222
BOOL _hasDictionary2ObjectModifier;
2323
BOOL _hasObject2DictionaryModifier;
24-
BOOL _hasClassModifier;
2524

2625
BOOL _needsUpdate;
2726
/// = _allProperties.count
2827
NSInteger _propertiesCount;
2928
NSLocale * _Nullable _locale;
29+
NSNumberFormatter * _Nullable _numberFormatter;
30+
NSDateFormatter * _Nullable _dateFormatter;
3031
}
3132

3233
- (void)setNeedsUpdate;

Diff for: MJExtension/MJEClass.m

+23-3
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,14 @@ - (instancetype)initWithClass:(Class)cls {
8181

8282
// get generic classes
8383
MJEAddSelectorResult2Dictionary(currentClass,
84-
@selector(mj_objectClassInCollection),
84+
@selector(mj_classInfoInCollection),
8585
genericClasses);
86+
// Deprecated API compatible
87+
if (![currentClass respondsToSelector:@selector(mj_classInfoInCollection)]) {
88+
MJEAddSelectorResult2Dictionary(currentClass,
89+
@selector(mj_objectClassInArray),
90+
genericClasses);
91+
}
8692

8793
// get replaced keys
8894
MJEAddSelectorResult2Dictionary(currentClass,
@@ -113,10 +119,17 @@ - (instancetype)initWithClass:(Class)cls {
113119

114120
if ([cls respondsToSelector:@selector(mj_locale)]) {
115121
_locale = [(Class<MJEConfiguration>)cls mj_locale];
122+
} else if ([cls respondsToSelector:@selector(mj_numberLocale)]) { // Deprecated API compatible
123+
_locale = [(Class<MJEConfiguration>)cls mj_numberLocale];
124+
}
125+
if (_locale) {
126+
_numberFormatter = [NSNumberFormatter new];
127+
_numberFormatter.locale = _locale;
128+
}
129+
if ([cls respondsToSelector:@selector(mj_dateFormatter)]) {
130+
_dateFormatter = [(Class<MJEConfiguration>)cls mj_dateFormatter];
116131
}
117132
_hasOld2NewModifier = [cls instancesRespondToSelector:@selector(mj_newValueFromOldValue:property:)];
118-
// TODO: 4.0.0 new feature
119-
// _hasClassModifier = [
120133
_hasDictionary2ObjectModifier = [cls instancesRespondToSelector:@selector(mj_didConvertToObjectWithKeyValues:)];
121134
_hasObject2DictionaryModifier = [cls instancesRespondToSelector:@selector(mj_objectDidConvertToKeyValues:)];
122135

@@ -210,6 +223,13 @@ - (void)mj_handlePropertiesWithAllowedList:(NSSet *)allowedList
210223
}
211224
property.classInCollection = clazz;
212225

226+
// check the ability to change class.
227+
if (clazz) { // generic
228+
property->_hasClassModifier = [clazz respondsToSelector:@selector(mj_modifiedClassForDictionary:)];
229+
} else if (property.typeClass && property->_basicObjectType == MJEBasicTypeUndefined) { // common class (base class)
230+
property->_hasClassModifier = [property.typeClass respondsToSelector:@selector(mj_modifiedClassForDictionary:)];
231+
}
232+
213233
[allProperties addObject:property];
214234
}
215235

Diff for: MJExtension/MJExtensionConst.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ dispatch_once(&mje_onceTokenSemaphore, ^{ \
2929
});
3030

3131
// 过期
32-
#define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
32+
#define MJE_API_Deprecated(instead) API_DEPRECATED(instead, ios(2.0, 4.0))
3333

3434
// 构建错误
3535
#define MJExtensionBuildError(clazz, msg) \

Diff for: MJExtension/MJExtensionProtocols.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,26 @@
6464
/// @discussion - `key` is collection property name
6565
///
6666
/// - `value` is the class or class string for recongnizing in JSON.
67-
+ (NSDictionary *)mj_objectClassInCollection;
67+
+ (NSDictionary *)mj_classInfoInCollection;
68+
+ (NSDictionary *)mj_objectClassInArray MJE_API_Deprecated("Use +mj_classInfoCollection instead.");
6869

69-
/// Used in number formatter that covert a string to a number.
70+
+ (Class)mj_modifiedClassForDictionary:(NSDictionary *)dictionary;
71+
72+
/// Used in number formatter that coverts a string to a number.
7073
/// @discussion Normally "100,000" = 100000. But "100,000" = 100 in France.
7174
+ (NSLocale *)mj_locale;
75+
+ (NSLocale *)mj_numberLocale MJE_API_Deprecated("Use +mj_locale instead.");
76+
77+
/// Used in date formatter that converts a string to a date.
78+
/// @discussion Following formatters have already been existed by default.
79+
/// @code
80+
/// "yyyy-MM-dd"
81+
/// "yyyy-MM-dd'T'HH:mm:ss"
82+
/// "yyyy-MM-dd'T'HH:mm:ss.SSS"
83+
/// "yyyy-MM-dd'T'HH:mm:ssZ"
84+
/// "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
85+
/// @endcode
86+
+ (NSDateFormatter *)mj_dateFormatter;
7287

7388
/// Inherits configurations from super class or not.
7489
/// If not configurate, default value is YES.

Diff for: MJExtension/MJFoundation.m

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ + (BOOL)isClassFromFoundation:(Class)c
2626
[NSDate class],
2727
[NSValue class],
2828
[NSData class],
29-
[NSError class],
3029
[NSArray class],
3130
[NSDictionary class],
3231
[NSString class],

Diff for: MJExtension/MJProperty.h

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ NS_ASSUME_NONNULL_BEGIN
7777
@package
7878
/// has old to new value modifying method in Class containing.
7979
BOOL _hasValueModifier;
80+
/// has the ability to change generic class or common class(base class) based on value type.
81+
BOOL _hasClassModifier;
8082
/// If mappedMultiKeys exist, this value would be true
8183
BOOL _isMultiMapping;
8284
/// For multiple keys, keypath, subkeys mapping.
@@ -118,6 +120,8 @@ NS_ASSUME_NONNULL_BEGIN
118120
- (void)setValue:(id)value forObject:(id)object;
119121
- (id)valueForObject:(id)object;
120122

123+
- (id)valueInDictionary:(NSDictionary *)dictionary;
124+
121125
/// Initializer by a objc_property_t struct
122126
- (instancetype)initWithProperty:(objc_property_t)property inClass:(Class)cls;
123127

Diff for: MJExtension/MJProperty.m

+14
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,27 @@ - (id)valueForObject:(id)object
211211
return value;
212212
}
213213

214+
- (id)valueInDictionary:(NSDictionary *)dictionary {
215+
id value;
216+
for (NSArray *propertyKeys in _mappedMultiKeys) {
217+
value = dictionary;
218+
for (MJPropertyKey *key in propertyKeys) {
219+
value = [key valueInObject:value];
220+
if (!value) break;
221+
}
222+
if (value) return value;
223+
}
224+
return nil;
225+
}
226+
214227
/**
215228
* 设置成员变量的值
216229
*/
217230
- (void)setValue:(id)value forObject:(id)object {
218231
if (!_isKVCCompliant || value == nil) return;
219232
//FIXME: Bottleneck #4: Enhanced
220233
[object setValue:value forKey:self.name];
234+
// mj_msgSendOne(object, _setter, id, value);
221235
}
222236

223237
/** 对应着字典中的key */

Diff for: MJExtension/NSDate+MJExtension.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// NSDate+MJExtension.h
3+
// MJExtension
4+
//
5+
// Created by Frank on 2021/12/31.
6+
// Copyright © 2021 MJ Lee. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
@interface NSDate (MJExtension)
12+
13+
/// Return date string based on "yyyy-MM-dd'T'HH:mm:ssZ".
14+
- (NSString *)mj_defaultDateString;
15+
16+
@end

Diff for: MJExtension/NSDate+MJExtension.m

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// NSDate+MJExtension.m
3+
// MJExtension
4+
//
5+
// Created by Frank on 2021/12/31.
6+
// Copyright © 2021 MJ Lee. All rights reserved.
7+
//
8+
9+
#import "NSDate+MJExtension.h"
10+
11+
@implementation NSDate (MJExtension)
12+
13+
- (NSString *)mj_defaultDateString {
14+
static NSDateFormatter *formatter;
15+
static dispatch_once_t onceToken;
16+
dispatch_once(&onceToken, ^{
17+
formatter = [NSDateFormatter new];
18+
formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
19+
formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
20+
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
21+
});
22+
NSString *dateString = [formatter stringFromDate:self];
23+
return dateString;
24+
}
25+
26+
@end

0 commit comments

Comments
 (0)