Json视图工具

Simulator Screen Shot - iPhone 6 Plus - 2019-08-11 at 09.28.51.png

demo地址

简介

描述

BaseJsonViewController是一个用OC编写的提供了搜索插入编辑查看路径复制json/value等功能的Json可视化编辑工具。

由于网络数据请求下来后,APP端对json原数据的展示并不明朗。 修改网络数据只能通过Charles等抓包工具实现,受到的限制太多,所以诞生了在APP端直接对json进行查看、修改的Json视图工具:BaseJsonViewController

后续会对BaseJsonViewController进行持续的更新优化,欢迎使用。

主要功能

json结构展示:

  1. 一键压缩/展开 : 点击👀all 展开全部,点击🦆…压缩全部(需要注意的是,如果进行了压缩,处在插入状态的cell,将被删除)。
  2. 添加了层级的背景色、缩进等。默认最大展示6个层级,如果超过6个层级则跳转到新的页面,进行展示。
  3. 对类型的区分:分为Dictionary Array String Number
  4. 支持展开与收起功能,如果有子节点,则单击可以展开\收起。
  5. value的展示:一行cell 的 value默认最多展示两行。如果超过两行则压缩,并在底部展示。

搜索功能:

点击放大镜可以进入搜索页面

在源码中的位置:BaseJsonViewController->BaseJsonViewMainView->BaseJsonHeaderView->BaseJsonViewSearchView

  1. 搜索关键词:输入关键词,并且会自动进行搜索。

  2. 精准搜索:如果选中精准搜索,搜索策略将从containsString 变成 isEqualToString

注意:不管是否为精准搜索,都区分大小写。

  1. 搜索Editing:如果选中【搜Editing】按钮,则会搜索整个json中处在Editing状态并符合关键词搜索的数据。

注意:如果有处在插入状态的数据,这时候会自动被删除。

  1. 上一个\下一个:当搜索完成后,点击【上一个】、【下一个】自动跳转到相应的行。

  2. 查看总览:跳转到一个搜索结果总览控制器,显示了搜索结果的路径及`value

  3. 展示路径/搜索数量:当没有搜索条件(即:没有搜索词 、且搜Editing处于非选中状态)时,显示的是本控制器节点的路径。否则显示的是搜索结果数量。

  4. 展示路径/报错信息:具有滚动、放大功能,最大放大倍数为1倍

  5. 当搜索条件报错时,展示的是红色的报错信息。

  6. 当有搜索内容时,展示的是当前选中的搜索结果的节点路径,

删除功能

侧滑cell,出现删除功能(注意,因为侧滑功能比较多,所以在iphone5上面会导致删除功能被遮挡)

复制功能

复制功能分为两种:

  1. 如果侧滑cell对应的节点为ArrayDictionary 则会只能复制 json
  2. 如果侧滑cell 对应的节点为StringNumber则可以复制jsonvalue

编辑功能

侧滑cell,并点击编辑按钮开启编辑功能(下面把被编辑的节点称为Model,把Model的父节点称为SuperModel)。

  1. SuperModel类型对Modelkey 的影响:

  2. SuperModel点为Array类型:Model的key必须为空。

  3. SuperModelDictionary类型:Model的key必须有值。

  4. 点击取消按钮:取消所有修改。

  5. 点击完成按钮:

  6. 选中Number按钮,转成Numbser类型,输入的值必须为数字,否则会报错,并在报错位置进行显示。

  7. 选中String按钮,转成String类型,会有个默认值,默认值为""

  8. 选中json按钮:

    1. 如果ModelArray类型,则会把jons解析出来作为Model的子节点数据
    2. 如果ModelDictionary类型,则会直接解析Json,如果json内包含一个对象则该对象作Model的数据,把对象的Key作为Modelkey
  9. 选中Dictionary按钮:

    1. 如果ModelDictionary类型,则不会产生任何效果,否则Model清空子节点数据,并把Model转成Dictionary类型。
  10. 选中Array按钮:

    如果ModelArray类型,则不会产生任何效果,否则Model清空子节点数据,并把Model转成Array类型。

插入功能

侧滑cell,并点击插入按钮开启编辑功能

注意:如果在插入节点没有点击完成的情况下,对节点父节点执行收起操作,会自动删除刚刚插入的节点

注意:如果插入节点父节点为Dictionary类型,插入的节点父节点中的顺序不固定

把被编辑的节点称为Model

Model的父节点称为SuperModel

Model插入的子节点称为SubModel

SuperModel插入的子节点称为SuperSubModel)。

  1. 如果ModelDictionary则可以【插入子节点】或【插入父节点】。
    1. 【插入子节点】:
      1. 如果Model关闭状态,则自动展开Model,并在Model字节点的第一行插入一个新的节点SubModel,这时候,SubModel处于被编辑状态
      2. 注意:此时插入的SubModel在父节点Model无序
    2. 【插入父节点】:在Model的后面插入为SuperSubModel插入SuperSubModel
  2. 如果ModelArray类型,则可以【插入子节点】或【插入父节点】。
    1. 【插入子节点】:
      1. 如果Model展开状态,则自动压缩Model,并在Model字节点的第一行插入一个新的节点SubModel,这时候,SubModel处于被编辑状态
      2. 注意:此时插入的SubModel在父节点Model有序
    2. 【插入父节点】:在Model的后面插入为SuperSubModel插入SuperSubModel
  3. 如果ModelStringNumber类型,则可以【插入父节点】。在Model的后面插入为SuperSubModel插入SuperSubModel

实现思路

  1. json的解析
    1. 为了避免造成不必要的开销,对json解析的时机做了调整:
      1. 当节点A被打开时候,才会解析A的子节点数据。
      2. 在解析节点A数据时,优先获取缓存的A子节点数据。
      3. 在对A进行编辑插入时,对A的的子节点数据进行更新。
  2. 对视图的展示
    1. 对与无限层级缩放的视图来说,我们有必要把数据展平。
    2. 数据中创建一个用于标记层级的变量。来做一个无限缩放层级的假象。

实现细节

对于节点Model的定义

Model就代表了一个节点,所以Model的结构至关重要。

主要的属性:
  1. level:所处层级,在进行初始化时,根据父节点的level进行赋值。
@property (nonatomic,assign) NSInteger level;
  1. count:字节点的个数
@property (nonatomic,assign) NSInteger count;
  1. isOpen是否为打开状态
@property (nonatomic,assign) BOOL isOpen;
  1. originData:所有子节点的原始数据(可能为nil、Array、Dictionary、Number、String)
@property (nonatomic,strong) id originData;
  1. key:如果originData为字典,则key就是originData的key,否则为nil
@property (nonatomic,strong) NSString *key;
  1. data: originData 转化成的数据(可能为:nil、NSString、 NSArray<BaseJsonViewStepModel>、BaseJsonViewStepModel)
@property (nonatomic,strong) id data;
  1. originData:父节点( 在父节点创建子节点时,进行的赋值)
@property (nonatomic,weak) BaseJsonViewStepModel *superPoint;
  1. type:当前节点的类型
typedef enum : NSUInteger {
    BaseJsonViewStepModelType_Dictionary,
    BaseJsonViewStepModelType_Array,
    BaseJsonViewStepModelType_Number,
    BaseJsonViewStepModelType_String,
} BaseJsonViewStepModelType;

@property (nonatomic,assign) BaseJsonViewStepModelType type;
  1. 所处的状态
typedef enum : NSUInteger {
    BaseJsonViewStepCellStatus_Normal,
    BaseJsonViewStepCellStatus_EditingSelf,
    BaseJsonViewStepCellStatus_InsertItem,
} BaseJsonViewStepCellStatus;

@property (nonatomic,assign) BaseJsonViewStepCellStatus status;
对model的创建
  1. + (BaseJsonViewStepModel *) createStepModelWithOriginData: (id) data andKey: (NSString *)key
/**
 创建 一个model

 @param data 原始的子节点数据
 @param key 创建出的model对应的key
 @return model
 */
+ (BaseJsonViewStepModel *) createStepModelWithOriginData: (id) data andKey: (NSString *)key{
    BaseJsonViewStepModel *model = [BaseJsonViewStepModel new];
    model.originData = data;
    model.key = key;
    return model;
}   
  1. + (BaseJsonViewStepModel *(^)(id)) createWithID

类方法,返回一个blockblock 传入的是id类型的数据。数据可以是

  1. BaseJsonViewStepModel: 直接返回这个data。不再创建
  2. NSString:先转成字典,然后创建model

使用方法 BaseJsonViewStepModel.createWithId(data);

+ (BaseJsonViewStepModel *(^)(id)) createWithID {
    return ^(id data) {
        BaseJsonViewStepModel *model;
        if ([data isKindOfClass:BaseJsonViewStepModel.class]) {
            model = data;
        }
        if ([data isKindOfClass:NSString.class]) {
            NSDictionary *dic = BaseJsonViewManager.convertToDicWithJson(data);
            if (dic) {
                model = BaseJsonViewManager.convertToStepModelWithDic(dic);
            }
        }
        if (!model) {
            model = [BaseJsonViewStepModel createStepModelWithOriginData:data andKey:@""];
        }
        return model;
    };
}
搜索功能

搜索功能将会搜索出 所有的符合条件的model,并返回一个数组

isSearchEditing的筛选策略

  1. isSearchEditing:如果为true。
    1. 如果keynil,则搜索全部处在编辑状态的model。
    2. 如果key有值
      1. 如果isAccurateSearch为true:搜索所有keyvalue isEqualToString key的正在编辑状态的model
      2. 如果isAccurateSearch为true:搜索所有keyvalue containsString key的正在编辑状态的model
/**
 搜索

 @param key 搜索 关键字
 @param isAccurateSearch 是否为精准搜索(如果选中精准搜索,搜索策略将从`containsString` 变成 `isEqualToString`。不管是否为精准搜索,都区分大小写)
 @param isSearchEditing 是否搜索正在编辑状态的model
 @return 搜索结果
 */
- (NSMutableArray <BaseJsonViewStepModel *>*) searchWithKey:(NSString *)key andIsAccurateSearch: (BOOL) isAccurateSearch andIsSearchEditing:(BOOL) isSearchEditing {
    SBaseJsonViewStepSearchModelConfig config;
    config.isSearchEditing = isSearchEditing;
    config.isAccurateSearch = isAccurateSearch;
    config.key = key;
    config.model = self;
    return BaseJsonViewStepSearchModel.getResultWithSearchConfig(config);
}
删除功能

从父节点移除本节点

这个功能主要是找到originData中相同的元素,进行删除。

- (void) removeFromeSuper {
  
    if ([self.superPoint.originData isKindOfClass:NSArray.class]) {
        NSArray *array = self.superPoint.originData;
        NSMutableArray *arrayM = [[NSMutableArray alloc]initWithArray:array];
        [arrayM removeObject:self.originData];
        self.superPoint.originData = arrayM;
    }
    if ([self.superPoint.originData isKindOfClass:NSDictionary.class]) {
        NSDictionary *dic = self.superPoint.originData;
        NSMutableDictionary *dicM = [[NSMutableDictionary alloc]initWithDictionary:dic];
        NSString *key = self.key;
        if (key.length > 0) {
            dicM[self.key] = nil;
        }
        self.superPoint.originData = dicM;
    }
    
    [self.superPoint reloadDataWitOriginDataProperty];
}
插入节点

根据原始数据插入节点,并返回BaseJsonViewStepErrorModel

BaseJsonViewStepErrorModel 记录了插入时的错误信息

/**
 插入一个节点

 @param key 节点的key
 @param originData 节点的原始子节点y数据
 @param index 插入的位置
 @return 插入报错的model
 */
- (BaseJsonViewStepErrorModel *) insertWithKey: (NSString *)key
         andOriginData: (id) originData
              andIndex:(NSInteger) index;

根据model插入节点,并返回BaseJsonViewStepErrorModel

BaseJsonViewStepErrorModel 记录了插入时的错误信息



/**
 插入一个Model

 @param model 准备插入的 节点 model
 @param index 插入的位置
 @return 错误信息
 */
- (BaseJsonViewStepErrorModel *) insertWithModel: (BaseJsonViewStepModel *) model
                                        andIndex:(NSInteger) index;

最后

彩蛋:点击title会复制当前Controller展示的json数据呦~

工具刚刚成型,很多需要修改的地方,希望大家勇于提bug 谢谢~

demo地址

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

推荐阅读更多精彩内容