Json視圖工具

json 視圖工具

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)
@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地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章