Mantle,JSONModel,MJExtension,YYModel的比较

Mantle,JSONModel,MJExtension,YYModel的比较

把JSON数据转换为模型,其他的不多说,且看下面分解。

1.Mantle的使用

Mantle

上面介绍的很详细,具体其他用法自行查看。

基本步骤:

1.下载Mantle

2.创建model时候必须继承:MTLModel

3.model必须实现协议:MTLJSONSerializing

4.重写协议的一个方法:

//使用Mantle必须实现的协议 KVO的形式

+(NSDictionary *)JSONKeyPathsByPropertyKey

5.如果model里面属性有嵌套model 或者 属性需要做转换等就实现

+(NSValueTransformer *)JSONTransformerForKey:(NSString *)key

6.映射model主要涉及的类:MTLJSONAdapter

基本原理:

1.获取 model 的属性--> JSONKeyPath 映射字典

2.获取 model 的属性列表

3.根据 model 的方法给网络请求中返回的 JSON 字典中的 value 做值类型转化操作

4.使用 KVC 把值赋给 model 的属性,完成操作

测试API

如果你打开了,那数据基本上就是这样,仅供测试使用,无其他用途。

使用火狐浏览器打开如下:

仅供测试API.png
(1).Mantle 要求所有的 Model 都要继承于 MTLModel 并实现 MTLJSONSerializing 协议

MantleModel.h

@class MantleDataModel,MantleFeedModel,MantleDislikeModel,MantleCommentCountModel,MantlePicsModel,MantleListModel;

@protocol MantleFeedModel <NSObject>
@end
@protocol MantleDislikeModel <NSObject>
@end
@protocol MantleListModel <NSObject>
@end

@interface MantleModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,assign)int status;
@property (nonatomic,copy)NSString *resTime;
@property (nonatomic,copy)NSString *uni;
@property (nonatomic,copy)NSString *localUni;
@property (nonatomic,strong)MantleDataModel *data;
@end

@interface MantleDataModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,assign)NSInteger isIntro;
@property (nonatomic,copy)NSString *feedDownType;
@property (nonatomic,assign)NSInteger feedLastIndex;
@property (nonatomic,strong)NSArray <MantleFeedModel>*feed;
@property (nonatomic,copy)NSString *downText;
@property (nonatomic,copy)NSString *lastTimestampString;
@end

@interface MantleFeedModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,copy)NSString *newsId;
@property (nonatomic,copy)NSString *longTitle;
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *source;
@property (nonatomic,copy)NSString *link;
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *kpic;
@property (nonatomic,copy)NSString *intro;
@property (nonatomic,copy)NSString *pubDate;
@property (nonatomic,assign)NSInteger interestSwitch;
@property (nonatomic,strong)NSArray <MantleDislikeModel>*dislikeTags;
@property (nonatomic,copy)NSString *commentId;
@property (nonatomic,assign)NSInteger comment;
@property (nonatomic,strong)MantleCommentCountModel *commentCountInfo;
@property (nonatomic,copy)NSString *feedShowStyle;
@property (nonatomic,copy)NSString *category;
@property (nonatomic,strong)MantlePicsModel *pics;
@property (nonatomic,copy)NSString *recommendInfo;
@property (nonatomic,copy)NSString *articlePubDate;

@end

@interface MantleDislikeModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,assign)NSInteger commentStatus;
@property (nonatomic,assign)NSInteger qreply;
@property (nonatomic,assign)NSInteger show;
@property (nonatomic,assign)NSInteger all;
@property (nonatomic,assign)NSInteger praise;
@property (nonatomic,assign)NSInteger dispraise;
@end

@interface MantleCommentCountModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,assign)NSInteger commentStatus;
@property (nonatomic,assign)NSInteger qreply;
@property (nonatomic,assign)NSInteger show;
@property (nonatomic,assign)NSInteger all;
@property (nonatomic,assign)NSInteger praise;
@property (nonatomic,assign)NSInteger dispraise;
@end

@interface MantlePicsModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,strong)NSArray <MantleListModel>*list;
@property (nonatomic,assign)NSInteger total;
@end

@interface MantleListModel : MTLModel<MTLJSONSerializing>
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *alt;
@property (nonatomic,copy)NSString *kpic;
@end

MantleModel.m

@implementation MantleModel
//必须实现
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{@"status":@"status",
             @"resTime":@"resTime",
             @"uni":@"uni",
             @"localUni":@"localUni",
             @"data":@"data"};
}

// 模型里面的模型
+ (NSValueTransformer *)dataTransformer {
    return [MTLJSONAdapter dictionaryTransformerWithModelClass:MantleDataModel.class];
}

//实现类似+<key>JSONTransformer的方法,来指定某个属性从字典里面取值后的类型(或怎么取值):
//SEL selector = MTLSelectorWithKeyPattern(key, "JSONTransformer");
//注意:属性名+JSONTransformer
+ (NSValueTransformer *)resTimeJSONTransformer
{
    return [self dateJSONTransformer];
}

//日期格式转换
+ (NSValueTransformer *)dateJSONTransformer
{
    return [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) {
        if (success) {
            NSTimeInterval secs = [value doubleValue];
            return [NSDate dateWithTimeIntervalSince1970:secs];
        }else {
            return @([value timeIntervalSince1970]);
        }
    }];
}

@end

@implementation MantleDataModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{@"isIntro":@"isIntro",
             @"feedDownType":@"feedDownType",
             @"feedLastIndex":@"feedLastIndex",
             @"feed":@"feed",
             @"downText":@"downText",
             @"lastTimestamp":@"lastTimestamp"
             };
}

// 模型里面的数组
+ (NSValueTransformer *)feedTransformer {
    return [MTLJSONAdapter arrayTransformerWithModelClass:MantleFeedModel.class];
}

@end

@implementation MantleFeedModel

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    return mapping;
}

@end

@implementation MantleDislikeModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    return mapping;
}

@end

@implementation MantleCommentCountModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    return mapping;
}

@end

@implementation MantlePicsModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    return mapping;
}

@end

@implementation MantleListModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    return mapping;
}

@end
(2).简单说明:

对JSONKeyPathsByPropertyKey上面写了两种,其中的MantleDataModel你可以利用JSONKeyPathsByPropertyKey把所有属性按字典列出来:

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{@"isIntro":@"isIntro",
             @"feedDownType":@"feedDownType",
             @"feedLastIndex":@"feedLastIndex",
             @"feed":@"feed",
             @"downText":@"downText",
             @"lastTimestamp":@"lastTimestamp"
             };
}

或许你也可以直接写成这样:

 + (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    mapping[@"lastTimestampString"] = @"lastTimestamp";
    return mapping;
}

利用属性名+JSONTransformer,对于dateJSONTransformer其中简单进行日期转换。

+ (NSValueTransformer *)dateJSONTransformer
{
    return [MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError *__autoreleasing *error) {
        if (success) {
            NSTimeInterval secs = [value doubleValue];
            return [NSDate dateWithTimeIntervalSince1970:secs];
        }else {
            return @([value timeIntervalSince1970]);
        }
    }];
}

进行关键字替换:

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    NSMutableDictionary *mapping = [[NSDictionary mtl_identityPropertyMapWithModel:self] mutableCopy];
    mapping[@"lastTimestampString"] = @"lastTimestamp";
    return mapping;
}

当你的 Model 里的所有属性的名字和 JSON 里的所有 key 的名字完全相同的时候,你就可以用这个方法直接生成一个 NSDictionary, 直接返回:

比如这个:

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{@"status":@"status",
             @"resTime":@"resTime",
             @"uni":@"uni",
             @"localUni":@"localUni",
             @"data":@"data"};
}

你也可以直接这样:

 + (NSDictionary *)JSONKeyPathsByPropertyKey {
 return [NSDictionary mtl_identityPropertyMapWithModel:self];
 }
(3)其他

注意: Mantle不会自动转类型,如:String->Int, 一旦类型不匹配,直接crash。
Json->Model 该方法会调用key-key map方法。

self.userForMantle = [MTLJSONAdapter modelOfClass:[UserForMantle class] fromJSONDictionary:self.JSONDict error:nil];

这种方式只是简单的使用KVC进行赋值。不会调用key-key map方法, 要求属性和JSON字典中的key名称相同,否则就crash。

self.userForMantle = [UserForMantle modelWithDictionary:self.JSONDict error:&error];

Model -> JSON
一旦有属性为nil, Mantle会转换成NSNull对象放到JSON字典中,这里有一个坑,使用NSUserDefault存储这样的JSON字典时,程序crash,原因是不可以包含NSNull对象。

NSDictionary *jsonDict = [MTLJSONAdapter JSONDictionaryFromModel:self.userForMantle error:nil];

优点:

1.修改字段映射时相当简便

2.扩展时相对方便

3.可以实现更多复杂的映射关系和数值转换

4.实现了NSCopying和NSCoding协议,可以轻松序列化

缺点:

1.基于运行时属性映射,对性能有一定影响

2.有部分容错处理需要自行解决

其他等等可以自行查看Mantle

2.JSONModel

JSONModel

【对应上面测试API,数据仅供测试使用】:

(1). 所有Model类继承于JSONModel

JSONModel.h

@class dataModel,commentCountModel,picsModel;

@protocol feedModel <NSObject>
@end
@protocol dislikeModel <NSObject>
@end
@protocol commentCountModel <NSObject>
@end
@protocol picsModel <NSObject>
@end
@protocol listModel <NSObject>
@end

@interface BaseJsonModel : JSONModel

@property (nonatomic,assign)int status;
@property (nonatomic,copy)NSString *resTime;
@property (nonatomic,copy)NSString <Optional>*uni;
@property (nonatomic,copy)NSString *localUni;
@property (nonatomic,strong)dataModel *data;

@end

@interface dataModel : JSONModel
@property (nonatomic,assign)NSInteger isIntro;
@property (nonatomic,copy)NSString *feedDownType;
@property (nonatomic,assign)NSInteger feedLastIndex;
@property (nonatomic,strong)NSArray<feedModel>*feed;
@property (nonatomic,copy)NSString *downText;
@property (nonatomic,copy)NSString *lastTimestamp;
@end

@interface feedModel : JSONModel
@property (nonatomic,copy)NSString *newsId;
@property (nonatomic,copy)NSString *longTitle;
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *source;
@property (nonatomic,copy)NSString *link;
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *kpic;
//@property (nonatomic,copy)NSString *intro;
@property (nonatomic,copy)NSString *des;
@property (nonatomic,copy)NSString *pubDate;
@property (nonatomic,assign)NSInteger interestSwitch;
@property (nonatomic,strong)NSArray <dislikeModel>*dislikeTags;
@property (nonatomic,copy)NSString *commentId;
@property (nonatomic,assign)NSInteger comment;
@property (nonatomic,strong)commentCountModel *commentCountInfo;
@property (nonatomic,copy)NSString *feedShowStyle;
@property (nonatomic,copy)NSString *category;
@property (nonatomic,strong)picsModel *pics;
@property (nonatomic,copy)NSString *recommendInfo;
@end

@interface dislikeModel : JSONModel

@end

@interface commentCountModel : JSONModel
@property (nonatomic,assign)NSInteger commentStatus;
@property (nonatomic,assign)NSInteger qreply;
@property (nonatomic,assign)NSInteger show;
@property (nonatomic,assign)NSInteger all;
@property (nonatomic,assign)NSInteger praise;
@property (nonatomic,assign)NSInteger dispraise;
@end

@interface picsModel : JSONModel
@property (nonatomic,strong)NSArray <listModel>*list;
@property (nonatomic,assign)NSInteger total;
@end

@interface listModel : JSONModel
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *alt;
@property (nonatomic,copy)NSString *kpic;
@end

JSONModel.m

@implementation BaseJsonModel

@end
@implementation dataModel

@end
@implementation feedModel
+ (JSONKeyMapper *)keyMapper {
    return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:
            @{
              @"des":@"intro",
              }];
}
@end
@implementation dislikeModel

@end
@implementation commentCountModel

@end
@implementation picsModel

@end
@implementation listModel

@end

(2).简单说明:

关键值替换

+ (JSONKeyMapper *)keyMapper {
    return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:
            @{
              @"des":@"intro",
              }];
}

忽略属性

 @property (strong, nonatomic) NSString<Ignore>* qreply;

设置某个字段为可选(为空)

 @property (strong, nonatomic) NSString<Optional>* qreply;

设置所有的属性为可选(为空)

+(BOOL)propertyIsOptional:(NSString*)propertyName
 {
 return YES;
 }

自动把下划线方式的命名转为驼峰命名属性,大小写转换

 {
 "list_name": wang,
 "list_pic" : @"11",
 }

生成模型:

 @interface ListModel : JSONModel
 
 @property (copy, nonatomic) int listName;
 @property (assign, nonatomic) float listPic;
 
 @end
 
 @implementation ListModel
 
 +(JSONKeyMapper*)keyMapper
 {
 return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];
 }

其他等等可以自行查看JSONModel

3.YYModel

YYModel

(1).相比上面不用继承

YYJSONModel.h

@class YYJSONDataModel,YYJSONFeedModel;

@interface YYJSONModel : NSObject
@property (nonatomic,assign)int status;
@property (nonatomic,copy)NSString *resTime;
@property (nonatomic,copy)NSString *uni;
@property (nonatomic,copy)NSString *localUni;
@property (nonatomic,strong)YYJSONDataModel *data;
@end

@interface YYJSONDataModel : NSObject
@property (nonatomic,assign)NSInteger isIntro;
@property (nonatomic,copy)NSString *feedDownType;
@property (nonatomic,assign)NSInteger feedLastIndex;
@property (nonatomic,strong)NSArray *feed;
@property (nonatomic,copy)NSString *downText;
@property (nonatomic,copy)NSString *lastTimestamp;
@end

@interface YYJSONFeedModel : NSObject
@property (nonatomic,copy)NSString *newsId;
@property (nonatomic,copy)NSString *longTitle;
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *source;
@property (nonatomic,copy)NSString *link;
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *kpic;
@property (nonatomic,copy)NSString *des;
@property (nonatomic,copy)NSString *pubDate;
@property (nonatomic,assign)NSInteger interestSwitch;
@end

YYJSONModel.m

@implementation YYJSONModel

@end

@implementation YYJSONDataModel
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
+ (NSDictionary *)modelContainerPropertyGenericClass {
    return @{@"feed" : @"YYJSONFeedModel" };
    /*
     **@"feed" : [YYJSONFeedModel class],
     @"feed" : YYJSONFeedModel.class,
     @"feed" : @"YYJSONFeedModel"
     */
}

@end

@implementation YYJSONFeedModel
+ (NSDictionary *)modelCustomPropertyMapper {
    return @{@"des":@"intro"};
}
@end

(2).简单说明

json转模型

方法: + (instancetype)yy_modelWithJSON:(id)json;

模型转字符串

方法: - (NSString *)yy_modelToJSONString

字典转模型

方法: + (instancetype)yy_modelWithDictionary:(NSDictionary *)dictionary ;

声明数组、字典或者集合里的元素类型时要重写

方法: + (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass;

字典里的key值与模型的属性值不一致要重复

方法: + (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper;

下面两者是属性值在两个dic与模型之间的转化方法

方法: - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic ;

方法: - (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic;

你可以把一个或一组 json key (key path) 映射到一个或多个属性。如果一个属性没有映射关系,那默认会使用相同属性名作为映射。

在 json->model 的过程中:如果一个属性对应了多个 json key,那么转换过程会按顺序查找,并使用第一个不为空的值。

在 model->json 的过程中:如果一个属性对应了多个 json key (key path),那么转换过程仅会处理第一个 json key (key path);如果多个属性对应了同一个 json key,则转换过过程会使用其中任意一个不为空的值。

被包含的Model什么都不用做,如果属性名不对应,也要实现映射的方法
“+ (NSDictionary *)modelCustomPropertyMapper”

关键值替换

+ (NSDictionary *)modelCustomPropertyMapper {
    return @{@"des":@"intro"};
}

黑名单 与 白名单:

 @interface User
 @property NSString *name;
 @property NSUInteger age;
 @end
 
 @implementation Attributes
 // 如果实现了该方法,则处理过程中会忽略该列表内的所有属性
 + (NSArray *)modelPropertyBlacklist {
 return @[@"test1", @"test2"];
 }
 // 如果实现了该方法,则处理过程中不会处理该列表外的属性。
 + (NSArray *)modelPropertyWhitelist {
 return @[@"name"];
 }

数据校验与自定义转换

JSON:

{
"name":"Wang",
"timestamp" : 1544564567
}

Model:

 @interface User
 @property NSString *name;
 @property NSDate *putDate;
 @end
 @implementation User
 
 // 当 JSON 转为 Model 完成后,该方法会被调用。
 // 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
 // 你也可以在这里做一些自动转换不能完成的工作。
 - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
 NSNumber *timestamp = dic[@"timestamp"];
 if (![timestamp isKindOfClass:[NSNumber class]]) return NO;
 _putDate = [NSDate dateWithTimeIntervalSince1970:timestamp.floatValue];
 return YES;
 }
 
 // 当 Model 转为 JSON 完成后,该方法会被调用。
 // 你可以在这里对数据进行校验,如果校验不通过,可以返回 NO,则该 Model 会被忽略。
 // 你也可以在这里做一些自动转换不能完成的工作。
 - (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic {
 if (! _putDate) return NO;
 dic[@"timestamp"] = @(n.timeIntervalSince1970);
 return YES;
 }

容器类属性

@interface YYJSONDataModel : NSObject
@property (nonatomic,assign)NSInteger isIntro;
@property (nonatomic,copy)NSString *feedDownType;
@property (nonatomic,assign)NSInteger feedLastIndex;
@property (nonatomic,strong)NSArray *feed;
@property (nonatomic,copy)NSString *downText;
@property (nonatomic,copy)NSString *lastTimestamp;
@end
// 返回容器类中的所需要存放的数据类型 (以 Class 或 Class Name 的形式)。
 + (NSDictionary *)modelContainerPropertyGenericClass {
 return @{@"feed" : [YYJSONFeedModel class]};
 }

其他等等可以自行查看YYModel

4.MJExtension

MJExtension

(1).MJExtension是一套字典和模型之间互相转换的超轻量级框架

MJExtensionModel.h

@class MJExtensionDataModel,MJExtensionFeedModel;

@interface MJExtensionModel : NSObject
@property (nonatomic,assign)int status;
@property (nonatomic,copy)NSString *resTime;
@property (nonatomic,copy)NSString *uni;
@property (nonatomic,copy)NSString *localUni;
@property (nonatomic,strong)MJExtensionDataModel *data;
@end

@interface MJExtensionDataModel : NSObject
@property (nonatomic,assign)NSInteger isIntro;
@property (nonatomic,copy)NSString *feedDownType;
@property (nonatomic,assign)NSInteger feedLastIndex;
@property (nonatomic,strong)NSArray *feed;
@property (nonatomic,copy)NSString *downText;
@property (nonatomic,copy)NSString *lastTimestamp;
@end

@interface MJExtensionFeedModel : NSObject
@property (nonatomic,copy)NSString *newsId;
@property (nonatomic,copy)NSString *longTitle;
@property (nonatomic,copy)NSString *title;
@property (nonatomic,copy)NSString *source;
@property (nonatomic,copy)NSString *link;
@property (nonatomic,copy)NSString *pic;
@property (nonatomic,copy)NSString *kpic;
//@property (nonatomic,copy)NSString *intro;
@property (nonatomic,copy)NSString *des;
@property (nonatomic,copy)NSString *pubDate;
@property (nonatomic,assign)NSInteger interestSwitch;
@end

MJExtensionModel.m

@implementation MJExtensionModel

@end

@implementation MJExtensionDataModel
+ (NSDictionary *)mj_objectClassInArray{
    return @{
             @"feed" : @"MJExtensionFeedModel",
             };
}

@end

@implementation MJExtensionFeedModel

+ (NSDictionary *)mj_replacedKeyFromPropertyName {
    return @{@"des":@"intro"};
}

@end

(2).简单说明

MJExtension是一套字典和模型之间互相转换的超轻量级框架

只需要一行代码,就能实现模型的所有属性进行Coding(归档和解档)

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

还是

其他等等可以自行查看MJExtension

iOS JSON 模型转换库评测

终于结束了。

最后凑个图.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349