PYJsonViewManager
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
Installation
PYJsonViewManager is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'PYJsonViewManager'
Author
LiPengYue, [email protected]
License
PYJsonViewManager is available under the MIT license. See the LICENSE file for more info.
简介
描述
BaseJsonViewController
是一个用OC
编写的提供了搜索
、插入
、编辑
、查看路径
、复制json/value
等功能的Json
可视化编辑工具。
由于网络数据请求下来后,
APP
端对json
原数据的展示并不明朗。 修改网络数据只能通过Charles
等抓包工具实现,受到的限制太多,所以诞生了在APP
端直接对json
进行查看、修改的Json
视图工具:BaseJsonViewController
。后续会对
BaseJsonViewController
进行持续的更新优化,欢迎使用。
主要功能
json结构展示:
- 一键压缩/展开 : 点击
👀all
展开全部,点击🦆…
压缩全部(需要注意的是,如果进行了压缩,处在插入状态的cell,将被删除)。 - 添加了层级的背景色、缩进等。默认最大展示6个层级,如果超过6个层级则跳转到新的页面,进行展示。
- 对类型的区分:分为
Dictionary
Array
String
Number
。 - 支持展开与收起功能,如果有子节点,则单击可以展开\收起。
- value的展示:一行cell 的 value默认最多展示两行。如果超过两行则压缩,并在底部展示。
搜索功能:
点击放大镜可以进入搜索页面
在源码中的位置:BaseJsonViewController
->BaseJsonViewMainView
->BaseJsonHeaderView
->BaseJsonViewSearchView
搜索关键词:输入关键词,并且会自动进行搜索。
精准搜索:如果选中精准搜索,搜索策略将从
containsString
变成isEqualToString
。注意:不管是否为精准搜索,都区分大小写。
- 搜索Editing:如果选中【搜Editing】按钮,则会搜索整个
json
中处在Editing
状态并符合关键词搜索的数据。注意:如果有处在
插入状态
的数据,这时候会自动被删除。
上一个\下一个:当搜索完成后,点击【上一个】、【下一个】自动跳转到相应的行。
查看总览:跳转到一个搜索结果总览控制器,显示了搜索结果的路径及`value
展示路径/搜索数量:当没有搜索条件(即:没有
搜索词
、且搜Editing
处于非选中状态)时,显示的是本控制器节点的路径。否则显示的是搜索结果数量。展示路径/报错信息:具有滚动、放大功能,最大放大倍数为1倍
当搜索条件报错时,展示的是红色的报错信息。
当有搜索内容时,展示的是当前选中的搜索结果的节点路径,
删除功能
侧滑cell,出现删除功能(注意,因为侧滑功能比较多,所以在iphone5
上面会导致删除功能被遮挡)
复制功能
复制功能分为两种:
- 如果侧滑
cell
对应的节点为Array
或Dictionary
则会只能复制json
- 如果侧滑
cell
对应的节点为String
或Number
则可以复制json
与value
编辑功能
侧滑cell
,并点击编辑
按钮开启编辑功能(下面把被编辑的节点称为Model
,把Model
的父节点称为SuperModel
)。
SuperModel
类型对Model
的key
的影响:
SuperModel
点为Array
类型:Model的key
必须为空。
SuperModel
为Dictionary
类型:Model的key
必须有值。点击取消按钮:取消所有修改。
点击完成按钮:
选中
Number
按钮,转成Numbser
类型,输入的值必须为数字,否则会报错,并在报错位置进行显示。选中
String
按钮,转成String
类型,会有个默认值,默认值为""
。选中
json
按钮:
- 如果
Model
为Array
类型,则会把jons
解析出来作为Model
的子节点数据- 如果
Model
为Dictionary
类型,则会直接解析Json
,如果json
内包含一个对象则该对象作Model
的数据,把对象的Key
作为Model
的key
。选中
Dictionary
按钮:
- 如果
Model
为Dictionary
类型,则不会产生任何效果,否则Model
清空子节点数据,并把Model
转成Dictionary
类型。选中
Array
按钮:如果
Model
为Array
类型,则不会产生任何效果,否则Model
清空子节点数据,并把Model
转成Array
类型。
插入功能
侧滑cell
,并点击插入
按钮开启编辑功能
注意:如果在插入
的节点
没有点击完成的情况下,对节点
的父节点
执行收起
操作,会自动删除刚刚插入的节点
注意:如果插入节点
的父节
点为Dictionary
类型,插入的节点
在父节点
中的顺序
不固定
把被编辑的节点称为
Model
。把
Model
的父节点称为SuperModel
。把
Model
插入的子节点称为SubModel
。把
SuperModel
插入的子节点称为SuperSubModel
)。
- 如果
Model
为Dictionary
则可以【插入子节点】或【插入父节点】。
- 【插入子节点】:
- 如果
Model
为关闭
状态,则自动展开Model
,并在Model
字节点的第一行插入一个新的节点SubModel
,这时候,SubModel
处于被编辑状态
。- 注意:此时插入的
SubModel
在父节点Model
无序- 【插入父节点】:在
Model
的后面插入为SuperSubModel
插入SuperSubModel
- 如果
Model
为Array
类型,则可以【插入子节点】或【插入父节点】。
- 【插入子节点】:
- 如果
Model
为展开
状态,则自动压缩Model
,并在Model
字节点的第一行插入一个新的节点SubModel
,这时候,SubModel
处于被编辑状态
。- 注意:此时插入的
SubModel
在父节点Model
有序。- 【插入父节点】:在
Model
的后面插入为SuperSubModel
插入SuperSubModel
- 如果
Model
为String
或Number
类型,则可以【插入父节点】。在Model
的后面插入为SuperSubModel
插入SuperSubModel
实现思路
- 对
json
的解析 - 为了避免造成不必要的开销,对
json
解析的时机做了调整: - 当节点
A
被打开时候,才会解析A
的子节点数据。 - 在解析节点
A
数据时,优先获取缓存的A
子节点数据。 - 在对
A
进行编辑
或插入
时,对A
的的子节点数据进行更新。 - 对视图的展示
- 对与无限层级缩放的视图来说,我们有必要把数据展平。
- 数据中创建一个用于标记层级的变量。来做一个无限缩放层级的假象。
实现细节
对于节点Model的定义
Model
就代表了一个节点,所以Model
的结构至关重要。
主要的属性:
- level:所处层级,在进行初始化时,根据父节点的
level
进行赋值。
@property (nonatomic,assign) NSInteger level;
- count:字节点的个数
@property (nonatomic,assign) NSInteger count;
- isOpen是否为打开状态
@property (nonatomic,assign) BOOL isOpen;
- originData:所有子节点的原始数据(可能为nil、Array、Dictionary、Number、String)
@property (nonatomic,strong) id originData;
- key:如果originData为字典,则key就是originData的key,否则为nil
@property (nonatomic,strong) NSString *key;
- data: originData 转化成的数据(可能为:nil、NSString、 NSArray、BaseJsonViewStepModel)
@property (nonatomic,strong) id data;
- originData:父节点( 在父节点创建子节点时,进行的赋值)
@property (nonatomic,weak) BaseJsonViewStepModel *superPoint;
- type:当前节点的类型
typedef enum : NSUInteger {
BaseJsonViewStepModelType_Dictionary,
BaseJsonViewStepModelType_Array,
BaseJsonViewStepModelType_Number,
BaseJsonViewStepModelType_String,
} BaseJsonViewStepModelType;
@property (nonatomic,assign) BaseJsonViewStepModelType type;
- 所处的状态
typedef enum : NSUInteger {
BaseJsonViewStepCellStatus_Normal,
BaseJsonViewStepCellStatus_EditingSelf,
BaseJsonViewStepCellStatus_InsertItem,
} BaseJsonViewStepCellStatus;
@property (nonatomic,assign) BaseJsonViewStepCellStatus status;
对model的创建
+ (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;
}
+ (BaseJsonViewStepModel *(^)(id)) createWithID
类方法,返回一个
block
,block
传入的是id类型的数据。数据可以是
BaseJsonViewStepModel
: 直接返回这个data。不再创建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
的筛选策略
- isSearchEditing:如果为true。
- 如果
key
为nil
,则搜索全部处在编辑状态的model。- 如果
key
有值
- 如果
isAccurateSearch
为true:搜索所有key
或value
isEqualToString
key
的正在编辑状态的model
- 如果
isAccurateSearch
为true:搜索所有key
或value
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 谢谢~