项目作者: CoderMJLee

项目描述 :
JSON和模型之间快速,方便且非侵入式的转换框架。您的模型类不需要扩展任何基类。您无需修改​​任何模型文件。
高级语言: Objective-C
项目地址: git://github.com/CoderMJLee/MJExtension.git
创建时间: 2014-05-23T15:54:00Z
项目社区:https://github.com/CoderMJLee/MJExtension

开源协议:MIT License

下载


MJExtension

SPM supported
Carthage compatible
podversion
Platform

  • A fast, convenient and nonintrusive conversion framework between JSON and model.
  • 转换速度快、使用简单方便的字典转模型框架

📜✍🏻Release Notes: more details

Contents


Getting Started【开始使用】" class="reference-link"> Getting Started【开始使用】

Features【能做什么】" class="reference-link"> Features【能做什么】

  • MJExtension是一套字典和模型之间互相转换的超轻量级框架
  • JSON —> ModelCore Data Model
  • JSONString —> ModelCore Data Model
  • ModelCore Data Model —> JSON
  • JSON Array —> Model ArrayCore Data Model Array
  • JSONString —> Model ArrayCore Data Model Array
  • Model ArrayCore Data Model Array —> JSON Array
  • Coding all properties of a model with only one line of code.
    • 只需要一行代码,就能实现模型的所有属性进行Coding / SecureCoding(归档和解档)

Installation【安装】" class="reference-link"> Installation【安装】

CocoaPods【使用CocoaPods】

  1. pod 'MJExtension'

Carthage

  1. github "CoderMJLee/MJExtension"

Swift Package Manager

Released from 3.4.0

Manually【手动导入】

  • Drag all source files under folder MJExtension to your project.【将MJExtension文件夹中的所有源代码拽入项目中】
  • Import the main header file:#import "MJExtension.h"【导入主头文件:#import "MJExtension.h"

Examples【示例】" class="reference-link"> Examples【示例】

Add MJKeyValue protocol to your model if needed【如果有需要, 请在模型中加入 MJKeyValue 协议】

Usage in Swift [关于在Swift中使用MJExtension] ‼️" class="reference-link"> Usage in Swift [关于在Swift中使用MJExtension] ‼️

Example:

  1. @objc(MJTester)
  2. @objcMembers
  3. class MJTester: NSObject {
  4. // make sure to use `dynamic` attribute for basic type & must use as Non-Optional & must set initial value
  5. dynamic var isSpecialAgent: Bool = false
  6. dynamic var age: Int = 0
  7. var name: String?
  8. var identifier: String?
  9. }
  1. @objc or @objcMembers attributes should be added to class or property for declaration of Objc accessibility [在 Swift4 之后, 请在属性前加 @objc 修饰或在类前增加 @objcMembers. 以保证 Swift 的属性能够暴露给 Objc 使用. ]
  2. If you let Bool & Int as property type, make sure that using dynamic to attribute it. It must be Non-Optional type and assign a default value.[如果要使用 BoolInt 等 Swfit 专用基本类型, 请使用 dynamic 关键字修饰, 类型为 Non-Optional, 並且给定初始值.]

纯Swift版的JSON与Model转换框架已经开源上架

  • KakaJSON
  • 中文教程
  • 如果你的项目是用Swift写的Model,墙裂推荐使用KakaJSON
    • 已经对各种常用的数据场景进行了大量的单元测试
    • 简单易用、功能丰富、转换快速

The most simple JSON -> Model【最简单的字典转模型】" class="reference-link"> The most simple JSON -> Model【最简单的字典转模型】

  1. typedef enum {
  2. SexMale,
  3. SexFemale
  4. } Sex;
  5. @interface User : NSObject
  6. @property (copy, nonatomic) NSString *name;
  7. @property (copy, nonatomic) NSString *icon;
  8. @property (assign, nonatomic) unsigned int age;
  9. @property (copy, nonatomic) NSString *height;
  10. @property (strong, nonatomic) NSNumber *money;
  11. @property (assign, nonatomic) Sex sex;
  12. @property (assign, nonatomic, getter=isGay) BOOL gay;
  13. @end
  14. /***********************************************/
  15. NSDictionary *dict = @{
  16. @"name" : @"Jack",
  17. @"icon" : @"lufy.png",
  18. @"age" : @20,
  19. @"height" : @"1.55",
  20. @"money" : @100.9,
  21. @"sex" : @(SexFemale),
  22. @"gay" : @"true"
  23. // @"gay" : @"1"
  24. // @"gay" : @"NO"
  25. };
  26. // JSON -> User
  27. User *user = [User mj_objectWithKeyValues:dict];
  28. NSLog(@"name=%@, icon=%@, age=%zd, height=%@, money=%@, sex=%d, gay=%d", user.name, user.icon, user.age, user.height, user.money, user.sex, user.gay);
  29. // name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1

JSONString -> Model【JSON字符串转模型】" class="reference-link"> JSONString -> Model【JSON字符串转模型】

  1. // 1.Define a JSONString
  2. NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}";
  3. // 2.JSONString -> User
  4. User *user = [User mj_objectWithKeyValues:jsonString];
  5. // 3.Print user's properties
  6. NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age);
  7. // name=Jack, icon=lufy.png, age=20

Model contains model【模型中嵌套模型】" class="reference-link"> Model contains model【模型中嵌套模型】

  1. @interface Status : NSObject
  2. @property (copy, nonatomic) NSString *text;
  3. @property (strong, nonatomic) User *user;
  4. @property (strong, nonatomic) Status *retweetedStatus;
  5. @end
  6. /***********************************************/
  7. NSDictionary *dict = @{
  8. @"text" : @"Agree!Nice weather!",
  9. @"user" : @{
  10. @"name" : @"Jack",
  11. @"icon" : @"lufy.png"
  12. },
  13. @"retweetedStatus" : @{
  14. @"text" : @"Nice weather!",
  15. @"user" : @{
  16. @"name" : @"Rose",
  17. @"icon" : @"nami.png"
  18. }
  19. }
  20. };
  21. // JSON -> Status
  22. Status *status = [Status mj_objectWithKeyValues:dict];
  23. NSString *text = status.text;
  24. NSString *name = status.user.name;
  25. NSString *icon = status.user.icon;
  26. NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
  27. // text=Agree!Nice weather!, name=Jack, icon=lufy.png
  28. NSString *text2 = status.retweetedStatus.text;
  29. NSString *name2 = status.retweetedStatus.user.name;
  30. NSString *icon2 = status.retweetedStatus.user.icon;
  31. NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2);
  32. // text2=Nice weather!, name2=Rose, icon2=nami.png

Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】" class="reference-link"> Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】

  1. @interface Ad : NSObject
  2. @property (copy, nonatomic) NSString *image;
  3. @property (copy, nonatomic) NSString *url;
  4. @end
  5. @interface StatusResult : NSObject
  6. /** Contatins status model */
  7. @property (strong, nonatomic) NSMutableArray *statuses;
  8. /** Contatins ad model */
  9. @property (strong, nonatomic) NSArray *ads;
  10. @property (strong, nonatomic) NSNumber *totalNumber;
  11. @end
  12. /***********************************************/
  13. // Tell MJExtension what type of model will be contained in statuses and ads.
  14. [StatusResult mj_setupObjectClassInArray:^NSDictionary *{
  15. return @{
  16. @"statuses" : @"Status",
  17. // @"statuses" : [Status class],
  18. @"ads" : @"Ad"
  19. // @"ads" : [Ad class]
  20. };
  21. }];
  22. // Equals: StatusResult.m implements +mj_objectClassInArray method.
  23. NSDictionary *dict = @{
  24. @"statuses" : @[
  25. @{
  26. @"text" : @"Nice weather!",
  27. @"user" : @{
  28. @"name" : @"Rose",
  29. @"icon" : @"nami.png"
  30. }
  31. },
  32. @{
  33. @"text" : @"Go camping tomorrow!",
  34. @"user" : @{
  35. @"name" : @"Jack",
  36. @"icon" : @"lufy.png"
  37. }
  38. }
  39. ],
  40. @"ads" : @[
  41. @{
  42. @"image" : @"ad01.png",
  43. @"url" : @"http://www.ad01.com"
  44. },
  45. @{
  46. @"image" : @"ad02.png",
  47. @"url" : @"http://www.ad02.com"
  48. }
  49. ],
  50. @"totalNumber" : @"2014"
  51. };
  52. // JSON -> StatusResult
  53. StatusResult *result = [StatusResult mj_objectWithKeyValues:dict];
  54. NSLog(@"totalNumber=%@", result.totalNumber);
  55. // totalNumber=2014
  56. // Printing
  57. for (Status *status in result.statuses) {
  58. NSString *text = status.text;
  59. NSString *name = status.user.name;
  60. NSString *icon = status.user.icon;
  61. NSLog(@"text=%@, name=%@, icon=%@", text, name, icon);
  62. }
  63. // text=Nice weather!, name=Rose, icon=nami.png
  64. // text=Go camping tomorrow!, name=Jack, icon=lufy.png
  65. // Printing
  66. for (Ad *ad in result.ads) {
  67. NSLog(@"image=%@, url=%@", ad.image, ad.url);
  68. }
  69. // image=ad01.png, url=http://www.ad01.com
  70. // image=ad02.png, url=http://www.ad02.com

Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】" class="reference-link"> Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】

  1. @interface Bag : NSObject
  2. @property (copy, nonatomic) NSString *name;
  3. @property (assign, nonatomic) double price;
  4. @end
  5. @interface Student : NSObject
  6. @property (copy, nonatomic) NSString *ID;
  7. @property (copy, nonatomic) NSString *desc;
  8. @property (copy, nonatomic) NSString *nowName;
  9. @property (copy, nonatomic) NSString *oldName;
  10. @property (copy, nonatomic) NSString *nameChangedTime;
  11. @property (strong, nonatomic) Bag *bag;
  12. @end
  13. /***********************************************/
  14. // How to map
  15. [Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
  16. return @{
  17. @"ID" : @"id",
  18. @"desc" : @"description",
  19. @"oldName" : @"name.oldName",
  20. @"nowName" : @"name.newName",
  21. @"nameChangedTime" : @"name.info[1].nameChangedTime",
  22. @"bag" : @"other.bag"
  23. };
  24. }];
  25. // Equals: Student.m implements +mj_replacedKeyFromPropertyName method.
  26. NSDictionary *dict = @{
  27. @"id" : @"20",
  28. @"description" : @"kids",
  29. @"name" : @{
  30. @"newName" : @"lufy",
  31. @"oldName" : @"kitty",
  32. @"info" : @[
  33. @"test-data",
  34. @{
  35. @"nameChangedTime" : @"2013-08"
  36. }
  37. ]
  38. },
  39. @"other" : @{
  40. @"bag" : @{
  41. @"name" : @"a red bag",
  42. @"price" : @100.7
  43. }
  44. }
  45. };
  46. // JSON -> Student
  47. Student *stu = [Student mj_objectWithKeyValues:dict];
  48. // Printing
  49. NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@",
  50. stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime);
  51. // ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08
  52. NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price);
  53. // bagName=a red bag, bagPrice=100.700000

JSON array -> model array【将一个字典数组转成模型数组】" class="reference-link"> JSON array -> model array【将一个字典数组转成模型数组】

  1. NSArray *dictArray = @[
  2. @{
  3. @"name" : @"Jack",
  4. @"icon" : @"lufy.png"
  5. },
  6. @{
  7. @"name" : @"Rose",
  8. @"icon" : @"nami.png"
  9. }
  10. ];
  11. // JSON array -> User array
  12. NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray];
  13. // Printing
  14. for (User *user in userArray) {
  15. NSLog(@"name=%@, icon=%@", user.name, user.icon);
  16. }
  17. // name=Jack, icon=lufy.png
  18. // name=Rose, icon=nami.png

Model -> JSON【将一个模型转成字典】" class="reference-link"> Model -> JSON【将一个模型转成字典】

  1. // New model
  2. User *user = [[User alloc] init];
  3. user.name = @"Jack";
  4. user.icon = @"lufy.png";
  5. Status *status = [[Status alloc] init];
  6. status.user = user;
  7. status.text = @"Nice mood!";
  8. // Status -> JSON
  9. NSDictionary *statusDict = status.mj_keyValues;
  10. NSLog(@"%@", statusDict);
  11. /*
  12. {
  13. text = "Nice mood!";
  14. user = {
  15. icon = "lufy.png";
  16. name = Jack;
  17. };
  18. }
  19. */
  20. // More complex situation
  21. Student *stu = [[Student alloc] init];
  22. stu.ID = @"123";
  23. stu.oldName = @"rose";
  24. stu.nowName = @"jack";
  25. stu.desc = @"handsome";
  26. stu.nameChangedTime = @"2018-09-08";
  27. Bag *bag = [[Bag alloc] init];
  28. bag.name = @"a red bag";
  29. bag.price = 205;
  30. stu.bag = bag;
  31. NSDictionary *stuDict = stu.mj_keyValues;
  32. NSLog(@"%@", stuDict);
  33. /*
  34. {
  35. ID = 123;
  36. bag = {
  37. name = "\U5c0f\U4e66\U5305";
  38. price = 205;
  39. };
  40. desc = handsome;
  41. nameChangedTime = "2018-09-08";
  42. nowName = jack;
  43. oldName = rose;
  44. }
  45. */

Model array -> JSON array【将一个模型数组转成字典数组】" class="reference-link"> Model array -> JSON array【将一个模型数组转成字典数组】

  1. // New model array
  2. User *user1 = [[User alloc] init];
  3. user1.name = @"Jack";
  4. user1.icon = @"lufy.png";
  5. User *user2 = [[User alloc] init];
  6. user2.name = @"Rose";
  7. user2.icon = @"nami.png";
  8. NSArray *userArray = @[user1, user2];
  9. // Model array -> JSON array
  10. NSArray *dictArray = [User mj_keyValuesArrayWithObjectArray:userArray];
  11. NSLog(@"%@", dictArray);
  12. /*
  13. (
  14. {
  15. icon = "lufy.png";
  16. name = Jack;
  17. },
  18. {
  19. icon = "nami.png";
  20. name = Rose;
  21. }
  22. )
  23. */

Core Data" class="reference-link"> Core Data

  1. func json2CoreDataObject() {
  2. context.performAndWait {
  3. let object = MJCoreDataTester.mj_object(withKeyValues: Values.testJSONObject, context: context)
  4. // use the object
  5. }
  6. }
  7. func coreDataObject2JSON() {
  8. context.performAndWait {
  9. let dict = coreDataObject.mj_keyValues()
  10. // use dict
  11. }
  12. }

Coding (Archive & Unarchive methods are deprecated in iOS 12)" class="reference-link"> Coding (Archive & Unarchive methods are deprecated in iOS 12)

  1. #import "MJExtension.h"
  2. @implementation MJBag
  3. // NSCoding Implementation
  4. MJCodingImplementation
  5. @end
  6. /***********************************************/
  7. // what properties not to be coded
  8. [MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
  9. return @[@"name"];
  10. }];
  11. // Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
  12. // Create model
  13. MJBag *bag = [[MJBag alloc] init];
  14. bag.name = @"Red bag";
  15. bag.price = 200.8;
  16. NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"];
  17. // Encoding by archiving
  18. [NSKeyedArchiver archiveRootObject:bag toFile:file];
  19. // Decoding by unarchiving
  20. MJBag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
  21. NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
  22. // name=(null), price=200.800000

Secure Coding" class="reference-link"> Secure Coding

Using MJSecureCodingImplementation(class, isSupport) macro.

  1. @import MJExtension;
  2. // NSSecureCoding Implementation
  3. MJSecureCodingImplementation(MJBag, YES)
  4. @implementation MJBag
  5. @end
  6. /***********************************************/
  7. // what properties not to be coded
  8. [MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
  9. return @[@"name"];
  10. }];
  11. // Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
  12. // Create model
  13. MJBag *bag = [[MJBag alloc] init];
  14. bag.name = @"Red bag";
  15. bag.price = 200.8;
  16. bag.isBig = YES;
  17. bag.weight = 200;
  18. NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bag.data"];
  19. NSError *error = nil;
  20. // Encoding by archiving
  21. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bag requiringSecureCoding:YES error:&error];
  22. [data writeToFile:file atomically:true];
  23. // Decoding by unarchiving
  24. NSData *readData = [NSFileManager.defaultManager contentsAtPath:file];
  25. error = nil;
  26. MJBag *decodedBag = [NSKeyedUnarchiver unarchivedObjectOfClass:MJBag.class fromData:readData error:&error];
  27. MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);

Camel -> underline【统一转换属性名(比如驼峰转下划线)】" class="reference-link"> Camel -> underline【统一转换属性名(比如驼峰转下划线)】

  1. // Dog
  2. #import "MJExtension.h"
  3. @implementation Dog
  4. + (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName
  5. {
  6. // nickName -> nick_name
  7. return [propertyName mj_underlineFromCamel];
  8. }
  9. @end
  10. // NSDictionary
  11. NSDictionary *dict = @{
  12. @"nick_name" : @"旺财",
  13. @"sale_price" : @"10.5",
  14. @"run_speed" : @"100.9"
  15. };
  16. // NSDictionary -> Dog
  17. Dog *dog = [Dog mj_objectWithKeyValues:dict];
  18. // printing
  19. NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed);

NSString -> NSDate, nil -> @””【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@””)】" class="reference-link"> NSString -> NSDate, nil -> @””【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@””)】

  1. // Book
  2. #import "MJExtension.h"
  3. @implementation Book
  4. - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property
  5. {
  6. if ([property.name isEqualToString:@"publisher"]) {
  7. if (oldValue == nil) return @"";
  8. } else if (property.type.typeClass == [NSDate class]) {
  9. NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
  10. fmt.dateFormat = @"yyyy-MM-dd";
  11. return [fmt dateFromString:oldValue];
  12. }
  13. return oldValue;
  14. }
  15. @end
  16. // NSDictionary
  17. NSDictionary *dict = @{
  18. @"name" : @"5分钟突破iOS开发",
  19. @"publishedTime" : @"2011-09-10"
  20. };
  21. // NSDictionary -> Book
  22. Book *book = [Book mj_objectWithKeyValues:dict];
  23. // printing
  24. NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime);

NSDate -> NSString【模型转字典时, 修改 Date 类型至 String】" class="reference-link"> NSDate -> NSString【模型转字典时, 修改 Date 类型至 String】

  1. - (void)mj_objectDidConvertToKeyValues:(NSMutableDictionary *)keyValues {
  2. // NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  3. // formatter.dateFormat = @"yyy-MM-dd";
  4. // should use sharedFormatter for better performance
  5. keyValues[@"publishedTime"] = [sharedFormatter stringFromDate:self.publishedTime];
  6. }

More use cases【更多用法】" class="reference-link"> More use cases【更多用法】

  • Please reference to NSObject+MJKeyValue.h and NSObject+MJCoding.h

期待

  • 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有)
  • 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢
  • 如果你想为MJExtension输出代码,请拼命Pull Requests我