美文网首页
Objective-C Realm对象转JSONString

Objective-C Realm对象转JSONString

作者: 咕咕鷄 | 来源:发表于2016-12-08 09:11 被阅读0次

    原创文章转载请注明出处

    Realm是极好用的移动端数据库,我一直向朋友推荐,不仅仅是因为其跨平台的特性,还因为其自带的自动更新功能让程序结构变得简单。

    通常开发中我们会使用ORM框架,将JSON数据映射为对象,在Swift项目里我会用
    ObjectMapper进行处理。在老旧的OC项目中,由于历史原因没有使用ORM库,JSON数据自己解析,转换JSONString自然也要自己写。因为iOS自带的NSJSONSerialization可以将NSObject对象转换成NSData,再将NSData转换成NSString即可。

    去年将数据库切换成Realm以后,以为所有的RLMObject对象都是继承自NSObject也没太在意,结果昨天尝试将一个RLMObject对象转换成JSONString的时候发现通过NSJSONSerialization转换得到的NSDatanil

    跟着代码往下看,发现RLMObject对象的[xxx class]方法返回的Class名称和原对象不一样,前面还带了Realm的前缀,猜测这就是通过反射方法(
    class_copyPropertyList)去获取类属性失败的原因。爬了Github和StackOverflow都没有结果,有人报了类似的问题,但是只回复了已解决,却不告知如何解决,这种留图不留种的行为鄙视之👎。

    既然别人可以处理,想来应该也不难。翻一下RLMObject的头文件,找到RLMObjectSchema *objectSchema属性,再从RLMObjectSchema.h文件找到了className属性,打印了一下发现名称正确。既然有了类名,那么NSClassFromString就可以派上用场了。利用NSClassFromString创建Class,然后通过class_copyPropertyList函数获取类型属性,kvc读取对象的属性值,将对象转成NSDictionary,大功告成。

    分享一下代码,版权所有,使用时请将头部注释一起拷贝。

    //
    //  NSObject+JSONCategories.h
    //
    //  Created by chenjunsheng on 15/4/15.
    //  Copyright (c) 2015年 chenjunsheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface NSObject (JSONCategories)
    
    - (NSData *)JSONData;
    - (NSString *)JSONString;
    
    @end
    
    //
    //  NSObject+JSONCategories.m
    //
    //  Created by chenjunsheng on 15/4/15.
    //  Copyright (c) 2015年 chenjunsheng. All rights reserved.
    //
    
    #import "NSObject+JSONCategories.h"
    #import <Realm/Realm.h>
    
    @implementation NSObject (JSONCategories)
    
    - (NSDictionary *)getObjectData {
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        unsigned int propsCount;
     
        Class class = [self class];
        if ([self isKindOfClass:[RLMObject class]]) {
            class = NSClassFromString([[(RLMObject *)self objectSchema] className]);
        }
        objc_property_t *props = class_copyPropertyList(class, &propsCount);//获得属性列表
        for(int i = 0;i < propsCount; i++) {
            objc_property_t prop = props[i];
      
            NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];//获得属性的名称
            id value = [self valueForKey:propName];//kvc读值
            if(value == nil) {
                value = [NSNull null];
            } else {
                value = [value getObjectInternal];//自定义处理数组,字典,其他类
            }
            [dic setObject:value forKey:propName];
        }
        return dic;
    }
    
    - (id)getObjectInternal {
        if([self isKindOfClass:[NSString class]]
            || [self isKindOfClass:[NSNumber class]]
            || [self isKindOfClass:[NSNull class]]) {
            return self;
        }
     
        if([self isKindOfClass:[NSArray class]]) {
            NSArray *objarr = (NSArray *)self;
            NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count];
            for(int i = 0;i < objarr.count; i++) {
                [arr setObject:[[objarr objectAtIndex:i] getObjectInternal] atIndexedSubscript:i];
            }
            return arr;
        }
     
        if([self isKindOfClass:[NSDictionary class]]) {
            NSDictionary *objdic = (NSDictionary *)self;
            NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
            for(NSString *key in objdic.allKeys) {
                [dic setObject:[[objdic objectForKey:key] getObjectInternal] forKey:key];
            }
            return dic;
        }
        return [self getObjectData];
    }
    
    - (NSData *)JSONData {
        id obj = [self getObjectInternal];
        if (![NSJSONSerialization isValidJSONObject:obj])
            return nil;
     
        NSError *error = nil;
        NSData *result = [NSJSONSerialization dataWithJSONObject:obj
                  options:kNilOptions
                    error:&error];
        if(result.length > 0 && error == nil) {
            return result;
        }
        return nil;
    }
    
    - (NSString *)JSONString {
        NSData *jsonData = [self JSONData];
        NSString *result = nil;
        if(jsonData) {
            result = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
        }
        return result;
    }
    
    @end
    

    我是咕咕鸡,一个还在不停学习的全栈工程师。
    热爱生活,喜欢跑步,家庭是我不断向前进步的动力。

    相关文章

      网友评论

          本文标题:Objective-C Realm对象转JSONString

          本文链接:https://www.haomeiwen.com/subject/uhejmttx.html