Android 可视化修改json JsonPreviewer

项目中涉及到广告开发, 广告的装备是从API动态下发, 广告装备中,有很多业务相关参数,例如关闭或敞开、展现间隔、展现时间、重试次数、每日最大显示次数等。

开发时单个广告或许需要屡次修改装备来测验,为了便利测验,广告装备的json文件,有两种途径修改并生效

    1. 每次抓包修改装备
    1. 本地导入装备,从磁盘读取

但两种办法都有一定弊端

  • 首先测验时依靠电脑修改装备
  • 无法直观预览广告装备

考虑到开发时常常运用的Json格式化东西,既能够直观的预览Json, 还能够在线修改

那么就考虑将Json格式化东西移植到项目测验模块中

web网页能够处理Json格式化,同理在Android webView 中相同可行, 只需要引入处理格式化的JS代码即可。

查找材料,发现一个很实用的文章可视化修改json数据——json editor

开端处理

首先准备好WebView的壳子

    //初始化
    @SuppressLint("SetJavaScriptEnabled")
    private fun initWebView() {
        binding.webView.settings.apply {
            javaScriptEnabled = true
            javaScriptCanOpenWindowsAutomatically = true
            setSupportZoom(true)
            useWideViewPort = true
            builtInZoomControls = true
        }
        binding.webView.addJavascriptInterface(JsInterface(this@MainActivity), "json_parse")
    }
    //webView 与 Android 交互
    inner class JsInterface(context: Context) {
        private val mContext: Context
        init {
            mContext = context
        }
        @JavascriptInterface
        fun configContentChanged() {
            runOnUiThread {
                contentChanged = true
            }
        }
        @JavascriptInterface
        fun toastJson(msg: String?) {
            runOnUiThread { Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show() }
        }
        @JavascriptInterface
        fun saveConfig(jsonString: String?) {
            runOnUiThread {
                contentChanged = false
                Toast.makeText(mContext, "verification succeed", Toast.LENGTH_SHORT).show()
            }
        }
        @JavascriptInterface
        fun parseJsonException(e: String?) {
            runOnUiThread {
                e?.takeIf { it.isNotBlank() }?.let { alert(it) }
            }
        }
    }

加载json并在WebView中展现


        viewModel.jsonData.observe(this) { str ->
            if (str?.isNotBlank() == true) {
                binding.webView.loadUrl("javascript:showJson($str)")
            }
        }

WebView 加载预览页面

        binding.webView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                viewModel.loadAdConfig(this@MainActivity)
            }
        }
       binding.webView.loadUrl("file:///android_asset/preview_json.html")

Json 预览页, preview_json.html实现


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="jquery.json-viewer.css"
          rel="stylesheet" type="text/css">
</head>
<style type="text/css">
    #json-display {
        margin: 2em 0;
        padding: 8px 15px;
        min-height: 300px;
        background: #ffffff;
        color: #ff0000;
        font-size: 16px;
        width: 100%;
        border-color: #00000000;
  		border:none;
        line-height: 1.8;
    }
    #json-btn {
        display: flex;
        align-items: center;
        font-size: 18px;
  		width:100%;
  		padding: 10;
    }
    #format_btn {
  	    width: 50%;
  	    height: 36px;
    }
    #save_btn {
  	    width: 50%;
  	    height: 36px;
  	    margin-left: 4em;
    }
</style>
<body>
<div style="padding: 2px 2px 2px 2px;">
    <div id="json-btn" class="json-btn">
        <button type="button" id="format_btn" onclick="format_btn();">Format</button>
        <button type="button" id="save_btn" onclick="save_btn();">Verification</button>
    </div>
    <div>
        <pre id="json-display" contenteditable="true"></pre>
    </div>
    <br>
</div>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.json-viewer.js"></script>
<script>
    document.getElementById("json-display").addEventListener("input", function(){
            console.log("json-display input");
            json_parse.configContentChanged();
        }, false);
    function showJson(jsonObj){
        $("#json-display").jsonViewer(jsonObj,{withQuotes: true});//format json and display
    }
    function format_btn() {
        var my_json_val = $("#json-display").clone(false);
        my_json_val.find("a.json-placeholder").remove();
        var jsonval = my_json_val.text();
        var jsonObj = JSON.parse(jsonval);   //parse string to json
        $("#json-display").jsonViewer(jsonObj,{withQuotes: true});//format json and display
    }
    function save_btn() {
        var my_json_val = $("#json-display").clone(false);
        my_json_val.find("a.json-placeholder").remove();
        var jsonval = my_json_val.text();
        var saveFailed = false;
        try {
            var jsonObj = JSON.parse(jsonval); //parse
        } catch (e) {
            console.error(e.message);
            saveFailed = true;
            json_parse.parseJsonException(e.message); // throw exception
        }
        if(!saveFailed) {
            json_parse.saveConfig(jsonval);
        }
    }
</script>
</body>
</html>

这其中有两个问题需注意

    1. 假如value的值是url, 格式化后短少引号
      从json-viewer.js源码能够发现,源码中会判断value是否是url,假如是则直接输出

处理办法:在json 左右添加上双引号

    if (options.withLinks && isUrl(json)) {
        html += '<a href="' + json + '" class="json-string" target="_blank">' + '"'  +json + '"' + '</a>';
      } else {
        // Escape double quotes in the rendered non-URL string.
        json = json.replace(/&quot;/g, '\\&quot;');
        html += '<span class="json-string">"' + json + '"</span>';
      }
    1. 假如折叠后json-viewer会添加<a>标签,即使运用text()办法获取到纯文本数据,这里面也包含了“n items”的字符串,那么该怎么去除掉这些字符串呢?
 var my_json_val = $("#json-display").clone(false);
 my_json_val.find("a.json-placeholder").remove();

总结

运用时只需将json文件读取,传入preview_json.html的showJson办法

修改完毕后, 点击Save 即可保存

示例代码 Android 可视化修改json JsonPreviewer


(可视化修改json数据——json editor)[blog.51cto.com/u_5650011/5…]