Need help with MJExtension?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

CoderMJLee
8.5K Stars 2.2K Forks MIT License 342 Commits 6 Opened issues

Description

A fast, convenient and nonintrusive conversion framework between JSON and model. Your model class doesn't need to extend any base class. You don't need to modify any model file.

Services available

!
?

Need anything else?

Contributors list

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【开始使用】

Features【能做什么】

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

Installation【安装】

CocoaPods【使用CocoaPods】

pod 'MJExtension'

Carthage

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【示例】

Add

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

Usage in Swift [关于在Swift中使用MJExtension] ‼️

Example:

@objc(MJTester)
@objcMembers
class MJTester: NSObject {
    // make sure to use `dynamic` attribute for basic type & must use as Non-Optional & must set initial value
    dynamic var isSpecialAgent: Bool = false
    dynamic var age: Int = 0

var name: String?
var identifier: String?

}

  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
    .[如果要使用
    Bool
    Int
    等 Swfit 专用基本类型, 请使用
    dynamic
    关键字修饰, 类型为
    Non-Optional
    , 並且给定初始值.]

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

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

The most simple JSON -> Model【最简单的字典转模型】

typedef enum {
    SexMale,
    SexFemale
} Sex;

@interface User : NSObject @property (copy, nonatomic) NSString *name; @property (copy, nonatomic) NSString *icon; @property (assign, nonatomic) unsigned int age; @property (copy, nonatomic) NSString *height; @property (strong, nonatomic) NSNumber *money; @property (assign, nonatomic) Sex sex; @property (assign, nonatomic, getter=isGay) BOOL gay; @end

/***/

NSDictionary *dict = @{ @"name" : @"Jack", @"icon" : @"lufy.png", @"age" : @20, @"height" : @"1.55", @"money" : @100.9, @"sex" : @(SexFemale), @"gay" : @"true" // @"gay" : @"1" // @"gay" : @"NO" };

// JSON -> User User *user = [User mj_objectWithKeyValues:dict];

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); // name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1

JSONString -> Model【JSON字符串转模型】

// 1.Define a JSONString
NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}";

// 2.JSONString -> User User *user = [User mj_objectWithKeyValues:jsonString];

// 3.Print user's properties NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age); // name=Jack, icon=lufy.png, age=20

Model contains model【模型中嵌套模型】

@interface Status : NSObject
@property (copy, nonatomic) NSString *text;
@property (strong, nonatomic) User *user;
@property (strong, nonatomic) Status *retweetedStatus;
@end

/***/

NSDictionary *dict = @{ @"text" : @"Agree!Nice weather!", @"user" : @{ @"name" : @"Jack", @"icon" : @"lufy.png" }, @"retweetedStatus" : @{ @"text" : @"Nice weather!", @"user" : @{ @"name" : @"Rose", @"icon" : @"nami.png" } } };

// JSON -> Status Status *status = [Status mj_objectWithKeyValues:dict];

NSString *text = status.text; NSString *name = status.user.name; NSString *icon = status.user.icon; NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); // text=Agree!Nice weather!, name=Jack, icon=lufy.png

NSString *text2 = status.retweetedStatus.text; NSString *name2 = status.retweetedStatus.user.name; NSString *icon2 = status.retweetedStatus.user.icon; NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2); // text2=Nice weather!, name2=Rose, icon2=nami.png

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

@interface Ad : NSObject
@property (copy, nonatomic) NSString *image;
@property (copy, nonatomic) NSString *url;
@end

@interface StatusResult : NSObject /** Contatins status model / @property (strong, nonatomic) NSMutableArray statuses; / Contatins ad model */ @property (strong, nonatomic) NSArray *ads; @property (strong, nonatomic) NSNumber *totalNumber; @end

/***/

// Tell MJExtension what type of model will be contained in statuses and ads. [StatusResult mj_setupObjectClassInArray:^NSDictionary *{ return @{ @"statuses" : @"Status", // @"statuses" : [Status class], @"ads" : @"Ad" // @"ads" : [Ad class] }; }]; // Equals: StatusResult.m implements +mj_objectClassInArray method.

NSDictionary *dict = @{ @"statuses" : @[ @{ @"text" : @"Nice weather!", @"user" : @{ @"name" : @"Rose", @"icon" : @"nami.png" } }, @{ @"text" : @"Go camping tomorrow!", @"user" : @{ @"name" : @"Jack", @"icon" : @"lufy.png" } } ], @"ads" : @[ @{ @"image" : @"ad01.png", @"url" : @"http://www.ad01.com" }, @{ @"image" : @"ad02.png", @"url" : @"http://www.ad02.com" } ], @"totalNumber" : @"2014" };

// JSON -> StatusResult StatusResult *result = [StatusResult mj_objectWithKeyValues:dict];

NSLog(@"totalNumber=%@", result.totalNumber); // totalNumber=2014

// Printing for (Status *status in result.statuses) { NSString *text = status.text; NSString *name = status.user.name; NSString *icon = status.user.icon; NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); } // text=Nice weather!, name=Rose, icon=nami.png // text=Go camping tomorrow!, name=Jack, icon=lufy.png

// Printing for (Ad *ad in result.ads) { NSLog(@"image=%@, url=%@", ad.image, ad.url); } // image=ad01.png, url=http://www.ad01.com // image=ad02.png, url=http://www.ad02.com

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

@interface Bag : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) double price;
@end

@interface Student : NSObject @property (copy, nonatomic) NSString *ID; @property (copy, nonatomic) NSString *desc; @property (copy, nonatomic) NSString *nowName; @property (copy, nonatomic) NSString *oldName; @property (copy, nonatomic) NSString *nameChangedTime; @property (strong, nonatomic) Bag *bag; @end

/***/

// How to map [Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{ return @{ @"ID" : @"id", @"desc" : @"description", @"oldName" : @"name.oldName", @"nowName" : @"name.newName", @"nameChangedTime" : @"name.info[1].nameChangedTime", @"bag" : @"other.bag" }; }]; // Equals: Student.m implements +mj_replacedKeyFromPropertyName method.

NSDictionary *dict = @{ @"id" : @"20", @"description" : @"kids", @"name" : @{ @"newName" : @"lufy", @"oldName" : @"kitty", @"info" : @[ @"test-data", @{ @"nameChangedTime" : @"2013-08" } ] }, @"other" : @{ @"bag" : @{ @"name" : @"a red bag", @"price" : @100.7 } } };

// JSON -> Student Student *stu = [Student mj_objectWithKeyValues:dict];

// Printing NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@", stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime); // ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08 NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price); // bagName=a red bag, bagPrice=100.700000

JSON array -> model array【将一个字典数组转成模型数组】

NSArray *dictArray = @[
                         @{
                             @"name" : @"Jack",
                             @"icon" : @"lufy.png"
                         },
                         @{
                             @"name" : @"Rose",
                             @"icon" : @"nami.png"
                         }
                     ];

// JSON array -> User array NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray];

// Printing for (User *user in userArray) { NSLog(@"name=%@, icon=%@", user.name, user.icon); } // name=Jack, icon=lufy.png // name=Rose, icon=nami.png

Model -> JSON【将一个模型转成字典】

// New model
User *user = [[User alloc] init];
user.name = @"Jack";
user.icon = @"lufy.png";

Status *status = [[Status alloc] init]; status.user = user; status.text = @"Nice mood!";

// Status -> JSON NSDictionary statusDict = status.mj_keyValues; NSLog(@"%@", statusDict); / { text = "Nice mood!"; user = { icon = "lufy.png"; name = Jack; }; } */

// More complex situation Student *stu = [[Student alloc] init]; stu.ID = @"123"; stu.oldName = @"rose"; stu.nowName = @"jack"; stu.desc = @"handsome"; stu.nameChangedTime = @"2018-09-08";

Bag *bag = [[Bag alloc] init]; bag.name = @"a red bag"; bag.price = 205; stu.bag = bag;

NSDictionary stuDict = stu.mj_keyValues; NSLog(@"%@", stuDict); / { ID = 123; bag = { name = "\U5c0f\U4e66\U5305"; price = 205; }; desc = handsome; nameChangedTime = "2018-09-08"; nowName = jack; oldName = rose; } */

Model array -> JSON array【将一个模型数组转成字典数组】

// New model array
User *user1 = [[User alloc] init];
user1.name = @"Jack";
user1.icon = @"lufy.png";

User *user2 = [[User alloc] init]; user2.name = @"Rose"; user2.icon = @"nami.png";

NSArray *userArray = @[user1, user2];

// Model array -> JSON array NSArray dictArray = [User mj_keyValuesArrayWithObjectArray:userArray]; NSLog(@"%@", dictArray); / ( { icon = "lufy.png"; name = Jack; }, { icon = "nami.png"; name = Rose; } ) */

Core Data

func json2CoreDataObject() {
    context.performAndWait {
        let object = MJCoreDataTester.mj_object(withKeyValues: Values.testJSONObject, context: context)
        // use the object
    }
}

func coreDataObject2JSON() { context.performAndWait {
let dict = coreDataObject.mj_keyValues() // use dict } }

Coding (Archive & Unarchive methods are deprecated in iOS 12)

#import "MJExtension.h"

@implementation MJBag // NSCoding Implementation MJCodingImplementation @end

/***/

// what properties not to be coded [MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{ return @[@"name"]; }]; // Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.

// Create model MJBag *bag = [[MJBag alloc] init]; bag.name = @"Red bag"; bag.price = 200.8;

NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"]; // Encoding by archiving [NSKeyedArchiver archiveRootObject:bag toFile:file];

// Decoding by unarchiving MJBag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price); // name=(null), price=200.800000

Secure Coding

Using

MJSecureCodingImplementation(class, isSupport)
macro.
@import MJExtension;

// NSSecureCoding Implementation MJSecureCodingImplementation(MJBag, YES)

@implementation MJBag @end

/***/

// what properties not to be coded [MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{ return @[@"name"]; }]; // Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.

// Create model MJBag *bag = [[MJBag alloc] init]; bag.name = @"Red bag"; bag.price = 200.8; bag.isBig = YES; bag.weight = 200;

NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bag.data"];

NSError *error = nil; // Encoding by archiving NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bag requiringSecureCoding:YES error:&error]; [data writeToFile:file atomically:true];

// Decoding by unarchiving NSData *readData = [NSFileManager.defaultManager contentsAtPath:file]; error = nil; MJBag *decodedBag = [NSKeyedUnarchiver unarchivedObjectOfClass:MJBag.class fromData:readData error:&error]; MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);

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

// Dog
#import "MJExtension.h"

@implementation Dog

  • (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName { // nickName -> nick_name return [propertyName mj_underlineFromCamel]; } @end

// NSDictionary NSDictionary *dict = @{ @"nick_name" : @"旺财", @"sale_price" : @"10.5", @"run_speed" : @"100.9" }; // NSDictionary -> Dog Dog *dog = [Dog mj_objectWithKeyValues:dict];

// printing NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed);

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

// Book
#import "MJExtension.h"

@implementation Book

  • (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property { if ([property.name isEqualToString:@"publisher"]) {

      if (oldValue == nil) return @"";

    } else if (property.type.typeClass == [NSDate class]) {

      NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
      fmt.dateFormat = @"yyyy-MM-dd";
      return [fmt dateFromString:oldValue];

    }

    return oldValue; } @end

// NSDictionary NSDictionary *dict = @{ @"name" : @"5分钟突破iOS开发", @"publishedTime" : @"2011-09-10" }; // NSDictionary -> Book Book *book = [Book mj_objectWithKeyValues:dict];

// printing NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime);

NSDate -> NSString【模型转字典时, 修改 Date 类型至 String】

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

More use cases【更多用法】

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

期待

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

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.