Skip to content

Commit

Permalink
Boost speed for JSON->model conversion process.(#837 #835 #834)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfcon committed Dec 31, 2021
1 parent 69a5a90 commit ca2b9f2
Show file tree
Hide file tree
Showing 26 changed files with 703 additions and 112 deletions.
22 changes: 18 additions & 4 deletions MJExtension.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
0130EE80233C56D8008D2386 /* MJFrenchUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 0130EE7F233C56D8008D2386 /* MJFrenchUser.m */; };
0179886C24EFA460007F7FBC /* MJTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0179886B24EFA460007F7FBC /* MJTester.swift */; };
0179887024EFA58B007F7FBC /* SwiftModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */; };
01BC91E2277418DF004E5265 /* ValueTransformingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */; };
01BB00FD277EC1FF002EF5B3 /* DeprecatedAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */; };
01BB0100277EE8DC002EF5B3 /* NSDate+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; };
01BB0101277EE8DC002EF5B3 /* NSDate+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */; };
01BC91E2277418DF004E5265 /* ValueTransformingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */; };
01BC91E427741956004E5265 /* MJCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E327741956004E5265 /* MJCredential.swift */; };
01BC91E627741D8C004E5265 /* MJArticle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC91E527741D8C004E5265 /* MJArticle.swift */; };
01BC921327747C06004E5265 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC920B27747C05004E5265 /* Benchmark.swift */; };
Expand Down Expand Up @@ -95,7 +98,10 @@
0179886A24EFA460007F7FBC /* MJExtensionTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MJExtensionTests-Bridging-Header.h"; sourceTree = "<group>"; };
0179886B24EFA460007F7FBC /* MJTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJTester.swift; sourceTree = "<group>"; };
0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftModelTests.swift; sourceTree = "<group>"; };
01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValueTransformingTest.swift; sourceTree = "<group>"; };
01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeprecatedAPITests.swift; sourceTree = "<group>"; };
01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+MJExtension.h"; sourceTree = "<group>"; };
01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+MJExtension.m"; sourceTree = "<group>"; };
01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValueTransformingTests.swift; sourceTree = "<group>"; };
01BC91E327741956004E5265 /* MJCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJCredential.swift; sourceTree = "<group>"; };
01BC91E527741D8C004E5265 /* MJArticle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MJArticle.swift; sourceTree = "<group>"; };
01BC920B27747C05004E5265 /* Benchmark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Benchmark.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -268,6 +274,8 @@
2D2DBA062317DB32005A689E /* NSObject+MJKeyValue.m */,
2D2DBA142317DB33005A689E /* NSString+MJExtension.h */,
2D2DBA0B2317DB32005A689E /* NSString+MJExtension.mm */,
01BB00FE277EE8DB002EF5B3 /* NSDate+MJExtension.h */,
01BB00FF277EE8DB002EF5B3 /* NSDate+MJExtension.m */,
2D2DB9F62317DA64005A689E /* MJExtension.h */,
2D2DB9F72317DA64005A689E /* Info.plist */,
);
Expand All @@ -283,11 +291,12 @@
0107507526E88DA600AAEA10 /* CoreDataModel */,
2D2DBA5F2317DBDF005A689E /* Model */,
2D2DBA572317DBB9005A689E /* MJExtensionTests.m */,
01BC91E1277418DF004E5265 /* ValueTransformingTest.swift */,
01BC91E1277418DF004E5265 /* ValueTransformingTests.swift */,
010DF01D2761D90A0007EEF0 /* SpecialPropertyTypeTests.swift */,
0179886F24EFA58B007F7FBC /* SwiftModelTests.swift */,
01052EAC25F872D00049EC6F /* MultiThreadTests.swift */,
0107507D26E890C100AAEA10 /* CoreDataTests.swift */,
01BB00FC277EC1FF002EF5B3 /* DeprecatedAPITests.swift */,
01BC920B27747C05004E5265 /* Benchmark.swift */,
2D2DBA592317DBB9005A689E /* Info.plist */,
2D2DBA872317DCCF005A689E /* PrefixHeader.pch */,
Expand Down Expand Up @@ -345,6 +354,7 @@
2D2DBA262317DB33005A689E /* MJProperty.h in Headers */,
2D2DBA252317DB33005A689E /* MJPropertyKey.h in Headers */,
01F5515E2757144500518218 /* MJEClass.h in Headers */,
01BB0100277EE8DC002EF5B3 /* NSDate+MJExtension.h in Headers */,
2D2DB9F82317DA64005A689E /* MJExtension.h in Headers */,
2D2DBA222317DB33005A689E /* MJFoundation.h in Headers */,
);
Expand Down Expand Up @@ -538,6 +548,7 @@
2D2DBA1A2317DB33005A689E /* NSObject+MJKeyValue.m in Sources */,
2D2DBA192317DB33005A689E /* MJPropertyKey.m in Sources */,
2D2DBA202317DB33005A689E /* MJFoundation.m in Sources */,
01BB0101277EE8DC002EF5B3 /* NSDate+MJExtension.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -560,12 +571,13 @@
2D2DBA852317DBE0005A689E /* MJPerson.m in Sources */,
01BC921327747C06004E5265 /* Benchmark.swift in Sources */,
0107507C26E88EAC00AAEA10 /* MJCoreDataTester+CoreDataProperties.swift in Sources */,
01BC91E2277418DF004E5265 /* ValueTransformingTest.swift in Sources */,
01BC91E2277418DF004E5265 /* ValueTransformingTests.swift in Sources */,
2D2DBA7B2317DBE0005A689E /* MJBox.m in Sources */,
2D2DBA582317DBB9005A689E /* MJExtensionTests.m in Sources */,
010DF01E2761D90A0007EEF0 /* SpecialPropertyTypeTests.swift in Sources */,
2D2DBA7E2317DBE0005A689E /* MJBag.m in Sources */,
2D2DBA7F2317DBE0005A689E /* MJBaseObject.m in Sources */,
01BB00FD277EC1FF002EF5B3 /* DeprecatedAPITests.swift in Sources */,
2D2DBA7D2317DBE0005A689E /* MJBook.m in Sources */,
0107507E26E890C100AAEA10 /* CoreDataTests.swift in Sources */,
0107507826E88DD400AAEA10 /* MJCoreDataTestModel.xcdatamodeld in Sources */,
Expand Down Expand Up @@ -682,6 +694,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
Expand Down Expand Up @@ -742,6 +755,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
Expand Down
3 changes: 2 additions & 1 deletion MJExtension/MJEClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ NS_ASSUME_NONNULL_BEGIN
BOOL _hasOld2NewModifier;
BOOL _hasDictionary2ObjectModifier;
BOOL _hasObject2DictionaryModifier;
BOOL _hasClassModifier;

BOOL _needsUpdate;
/// = _allProperties.count
NSInteger _propertiesCount;
NSLocale * _Nullable _locale;
NSNumberFormatter * _Nullable _numberFormatter;
NSDateFormatter * _Nullable _dateFormatter;
}

- (void)setNeedsUpdate;
Expand Down
26 changes: 23 additions & 3 deletions MJExtension/MJEClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,14 @@ - (instancetype)initWithClass:(Class)cls {

// get generic classes
MJEAddSelectorResult2Dictionary(currentClass,
@selector(mj_objectClassInCollection),
@selector(mj_classInfoInCollection),
genericClasses);
// Deprecated API compatible
if (![currentClass respondsToSelector:@selector(mj_classInfoInCollection)]) {
MJEAddSelectorResult2Dictionary(currentClass,
@selector(mj_objectClassInArray),
genericClasses);
}

// get replaced keys
MJEAddSelectorResult2Dictionary(currentClass,
Expand Down Expand Up @@ -113,10 +119,17 @@ - (instancetype)initWithClass:(Class)cls {

if ([cls respondsToSelector:@selector(mj_locale)]) {
_locale = [(Class<MJEConfiguration>)cls mj_locale];
} else if ([cls respondsToSelector:@selector(mj_numberLocale)]) { // Deprecated API compatible
_locale = [(Class<MJEConfiguration>)cls mj_numberLocale];
}
if (_locale) {
_numberFormatter = [NSNumberFormatter new];
_numberFormatter.locale = _locale;
}
if ([cls respondsToSelector:@selector(mj_dateFormatter)]) {
_dateFormatter = [(Class<MJEConfiguration>)cls mj_dateFormatter];
}
_hasOld2NewModifier = [cls instancesRespondToSelector:@selector(mj_newValueFromOldValue:property:)];
// TODO: 4.0.0 new feature
// _hasClassModifier = [
_hasDictionary2ObjectModifier = [cls instancesRespondToSelector:@selector(mj_didConvertToObjectWithKeyValues:)];
_hasObject2DictionaryModifier = [cls instancesRespondToSelector:@selector(mj_objectDidConvertToKeyValues:)];

Expand Down Expand Up @@ -210,6 +223,13 @@ - (void)mj_handlePropertiesWithAllowedList:(NSSet *)allowedList
}
property.classInCollection = clazz;

// check the ability to change class.
if (clazz) { // generic
property->_hasClassModifier = [clazz respondsToSelector:@selector(mj_modifiedClassForDictionary:)];
} else if (property.typeClass && property->_basicObjectType == MJEBasicTypeUndefined) { // common class (base class)
property->_hasClassModifier = [property.typeClass respondsToSelector:@selector(mj_modifiedClassForDictionary:)];
}

[allProperties addObject:property];
}

Expand Down
2 changes: 1 addition & 1 deletion MJExtension/MJExtensionConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dispatch_once(&mje_onceTokenSemaphore, ^{ \
});

// 过期
#define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
#define MJE_API_Deprecated(instead) API_DEPRECATED(instead, ios(2.0, 4.0))

// 构建错误
#define MJExtensionBuildError(clazz, msg) \
Expand Down
19 changes: 17 additions & 2 deletions MJExtension/MJExtensionProtocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,26 @@
/// @discussion - `key` is collection property name
///
/// - `value` is the class or class string for recongnizing in JSON.
+ (NSDictionary *)mj_objectClassInCollection;
+ (NSDictionary *)mj_classInfoInCollection;
+ (NSDictionary *)mj_objectClassInArray MJE_API_Deprecated("Use +mj_classInfoCollection instead.");

/// Used in number formatter that covert a string to a number.
+ (Class)mj_modifiedClassForDictionary:(NSDictionary *)dictionary;

/// Used in number formatter that coverts a string to a number.
/// @discussion Normally "100,000" = 100000. But "100,000" = 100 in France.
+ (NSLocale *)mj_locale;
+ (NSLocale *)mj_numberLocale MJE_API_Deprecated("Use +mj_locale instead.");

/// Used in date formatter that converts a string to a date.
/// @discussion Following formatters have already been existed by default.
/// @code
/// "yyyy-MM-dd"
/// "yyyy-MM-dd'T'HH:mm:ss"
/// "yyyy-MM-dd'T'HH:mm:ss.SSS"
/// "yyyy-MM-dd'T'HH:mm:ssZ"
/// "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
/// @endcode
+ (NSDateFormatter *)mj_dateFormatter;

/// Inherits configurations from super class or not.
/// If not configurate, default value is YES.
Expand Down
1 change: 0 additions & 1 deletion MJExtension/MJFoundation.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ + (BOOL)isClassFromFoundation:(Class)c
[NSDate class],
[NSValue class],
[NSData class],
[NSError class],
[NSArray class],
[NSDictionary class],
[NSString class],
Expand Down
4 changes: 4 additions & 0 deletions MJExtension/MJProperty.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ NS_ASSUME_NONNULL_BEGIN
@package
/// has old to new value modifying method in Class containing.
BOOL _hasValueModifier;
/// has the ability to change generic class or common class(base class) based on value type.
BOOL _hasClassModifier;
/// If mappedMultiKeys exist, this value would be true
BOOL _isMultiMapping;
/// For multiple keys, keypath, subkeys mapping.
Expand Down Expand Up @@ -118,6 +120,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setValue:(id)value forObject:(id)object;
- (id)valueForObject:(id)object;

- (id)valueInDictionary:(NSDictionary *)dictionary;

/// Initializer by a objc_property_t struct
- (instancetype)initWithProperty:(objc_property_t)property inClass:(Class)cls;

Expand Down
14 changes: 14 additions & 0 deletions MJExtension/MJProperty.m
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,27 @@ - (id)valueForObject:(id)object
return value;
}

- (id)valueInDictionary:(NSDictionary *)dictionary {
id value;
for (NSArray *propertyKeys in _mappedMultiKeys) {
value = dictionary;
for (MJPropertyKey *key in propertyKeys) {
value = [key valueInObject:value];
if (!value) break;
}
if (value) return value;
}
return nil;
}

/**
* 设置成员变量的值
*/
- (void)setValue:(id)value forObject:(id)object {
if (!_isKVCCompliant || value == nil) return;
//FIXME: Bottleneck #4: Enhanced
[object setValue:value forKey:self.name];
// mj_msgSendOne(object, _setter, id, value);
}

/** 对应着字典中的key */
Expand Down
16 changes: 16 additions & 0 deletions MJExtension/NSDate+MJExtension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// NSDate+MJExtension.h
// MJExtension
//
// Created by Frank on 2021/12/31.
// Copyright © 2021 MJ Lee. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSDate (MJExtension)

/// Return date string based on "yyyy-MM-dd'T'HH:mm:ssZ".
- (NSString *)mj_defaultDateString;

@end
26 changes: 26 additions & 0 deletions MJExtension/NSDate+MJExtension.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// NSDate+MJExtension.m
// MJExtension
//
// Created by Frank on 2021/12/31.
// Copyright © 2021 MJ Lee. All rights reserved.
//

#import "NSDate+MJExtension.h"

@implementation NSDate (MJExtension)

- (NSString *)mj_defaultDateString {
static NSDateFormatter *formatter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
formatter = [NSDateFormatter new];
formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
});
NSString *dateString = [formatter stringFromDate:self];
return dateString;
}

@end
Loading

0 comments on commit ca2b9f2

Please sign in to comment.