• Android进阶之路 - Json解析异常


    在App与H5交互时,有一个调原生分享的需求,交互方面没有问题,因为分享需要多值,所以采用json进行传递,在app接收进行解析时遇到了这个解析异常 Value  of type java.lang.String cannot be converted to JSONObject`

    这可能是一个持续积累的过程,期待一起进步~

    JSONException:Value  of type java.lang.String cannot be converted to JSONObject (String无法转换为JSONObject )

    这个异常其实很常见,但是导致这种异常的场景可能各有不同 ~

    网上各位遇到的场景(解决)

    由于utf-8bom 头引起的问题,需去掉bom头(有人也尝试过在本地进行处理 json 字符串,将 bom 头去掉)= 无效,无兴趣可跳过!!!

    json 字符串格式也没问题,所以 可以肯定的是json字符内部有无法识别或者未知的字符,有人做了如下处理(根据json数据不同,过滤条件也不同

     String jsonStr = httpTools.doGet("URL接口地址",paramsBaseList);
     String json = jsonStr.substring(jsonStr.indexOf("{"), jsonStr.lastIndexOf("}") + 1);
    
    • 1
    • 2

    或 如下处理

     public String JSONTokener(String in) {
    	        // consume an optional byte order mark (BOM) if it exists
    	         if (in != null && in.startsWith("\ufeff")) {
    	            in = in.substring(1);
    	       }
    	      return in;
    	 }
     JSONObject obj = new JSONObject(JSONTokener(jsonStr));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    个人结论:首先我还没去了解这个 bom 头是啥… 其次这里有一点是有用的 → json字符内部有无法识别或者未知的字符

    最终 如下的处理方式帮到了我!!! 不过要注意是否处理下过期方法...

    • Kotlin
      val parser = JsonParser()
      val retVal: String = parser.parse(it).asString
    
    • 1
    • 2
    • Java
      JsonParser parser = new JsonParser();
      String retVal = parser.parse(param).getAsString();
    
    • 1
    • 2

    Look Here :然后再使用JSONObject解析 retVal 即可

    我遇到该问题的场景(解决)

    首先说明一下我分享相关的伪代码

    • app 提供给前端的方法
        /**
         * 分享
         */
        val shareInfo = MutableLiveData<String>()
    
        @Keep
        @JavascriptInterface
        fun appShare(param: String?, callbackId: String?) {
            Timber.e("appShare---> callbackId -->${callbackId} --param-->${param}")
            if (param.isNullOrEmpty()) return
            shareInfo.postValue(param.string())
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • js 调用 app 后的逻辑,主要看 jsonObject 解析部分
        javascriptMethod.shareInfo.observe(viewLifecycleOwner) { params ->
            val jsonObject = JSONObject(params)
            val url: String = jsonObject.optString("url", "")
            val title: String = jsonObject.optString("title", "")
            val desc: String = jsonObject.optString("desc", "")
            val icon: String = jsonObject.optString("icon", "")
            activity?.let { ShareService.service?.share(it, url, title, desc, icon) }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • app 获取到的 json 串

    这样的json串和我们平时接口返回的json串有所不同,但它也是正常的json串,所以需要处理内部的特殊字符,如 \ 、"" 等

    "{\"url\":\"https://baidu.com\",\"title\":\"测试JS方法\",\"desc\":\"测试H5调用APP分享页功能~~~\",\"icon\":\"https://mobile.baidu.com.cn/actapp/files/upload/images/32c72f230622.png\"}"
    
    • 1

    图示

    在这里插入图片描述

    • 处理特殊json串,解决问题
        /**
         * 分享
         */
        val shareInfo = MutableLiveData<Map<String, String?>>()
        @Keep
        @JavascriptInterface
        fun appShare(param: String?, callbackId: String?) {
            Timber.e("appShare---> callbackId -->${callbackId} --param-->${param}")
            if (param.isNullOrEmpty()) return
            try {
                val startIndex = if (param.startsWith("\"")) 1 else 0
                val endIndex = if (param.endsWith("\"")) param.length - 1 else param.length
                val result = param.substring(startIndex, endIndex).replace("\\", "")
                
                val jsonObject = JSONObject(result)
                val url = jsonObject.optString("url")
                val title = jsonObject.optString("title")
                val desc = jsonObject.optString("desc")
                val icon = jsonObject.optString("icon")
                if (url.isNullOrEmpty()) return
                shareInfo.postValue(mapOf("url" to url, "title" to title, "desc" to desc, "icon" to icon))
            } catch (throwable: Throwable) {
                Timber.e(throwable)
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    Java-I/O输入输出
    数学建模 Excel的批量写入与批量导出
    【Minecraft开服教学】使用 MCSM 面板一键搭建我的世界服务器 并使用内网穿透公网远程联机
    Python爬虫抓取经过JS加密的API数据的实现步骤
    C#WPF命令Command使用实例
    Java数据结构基础——泛型、通配符
    pytorch图像变换
    图像超分算法总结
    java datetime数据类型去掉时分秒
    「Java」Java面试宝典:全面覆盖常见问题和难点解析
  • 原文地址:https://blog.csdn.net/qq_20451879/article/details/128111581