diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt index f586e664..73ca39e2 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt @@ -102,7 +102,7 @@ object MmkvManager { return if (json.isNullOrBlank()) { mutableListOf() } else { - JsonUtil.fromJson(json, Array::class.java)?.toMutableList() ?: mutableListOf() + JsonUtil.fromJsonSafe(json, Array::class.java)?.toMutableList() ?: mutableListOf() } } @@ -144,7 +144,7 @@ object MmkvManager { if (json.isNullOrBlank()) { return null } - return JsonUtil.fromJson(json, ProfileItem::class.java) + return JsonUtil.fromJsonSafe(json, ProfileItem::class.java) } @@ -247,7 +247,7 @@ object MmkvManager { if (json.isNullOrBlank()) { return null } - return JsonUtil.fromJson(json, ServerAffiliationInfo::class.java) + return JsonUtil.fromJsonSafe(json, ServerAffiliationInfo::class.java) } /** @@ -374,7 +374,7 @@ object MmkvManager { decodeSubsList().forEach { key -> val json = subStorage.decodeString(key) if (!json.isNullOrBlank()) { - val item = JsonUtil.fromJson(json, SubscriptionItem::class.java) ?: SubscriptionItem() + val item = JsonUtil.fromJsonSafe(json, SubscriptionItem::class.java) ?: SubscriptionItem() subscriptions.add(SubscriptionCache(key, item)) } } @@ -420,7 +420,7 @@ object MmkvManager { */ fun decodeSubscription(subscriptionId: String): SubscriptionItem? { val json = subStorage.decodeString(subscriptionId) ?: return null - return JsonUtil.fromJson(json, SubscriptionItem::class.java) + return JsonUtil.fromJsonSafe(json, SubscriptionItem::class.java) } /** @@ -442,7 +442,7 @@ object MmkvManager { return if (json.isNullOrBlank()) { mutableListOf() } else { - JsonUtil.fromJson(json, Array::class.java)?.toMutableList() ?: mutableListOf() + JsonUtil.fromJsonSafe(json, Array::class.java)?.toMutableList() ?: mutableListOf() } } @@ -460,7 +460,7 @@ object MmkvManager { assetStorage.allKeys()?.forEach { key -> val json = assetStorage.decodeString(key) if (!json.isNullOrBlank()) { - val item = JsonUtil.fromJson(json, AssetUrlItem::class.java) ?: AssetUrlItem() + val item = JsonUtil.fromJsonSafe(json, AssetUrlItem::class.java) ?: AssetUrlItem() assetUrlItems.add(AssetUrlCache(key, item)) } } @@ -495,7 +495,7 @@ object MmkvManager { */ fun decodeAsset(assetid: String): AssetUrlItem? { val json = assetStorage.decodeString(assetid) ?: return null - return JsonUtil.fromJson(json, AssetUrlItem::class.java) + return JsonUtil.fromJsonSafe(json, AssetUrlItem::class.java) } //endregion @@ -510,7 +510,7 @@ object MmkvManager { fun decodeRoutingRulesets(): MutableList? { val ruleset = settingsStorage.decodeString(PREF_ROUTING_RULESET) if (ruleset.isNullOrEmpty()) return null - return JsonUtil.fromJson(ruleset, Array::class.java)?.toMutableList() ?: mutableListOf() + return JsonUtil.fromJsonSafe(ruleset, Array::class.java)?.toMutableList() ?: mutableListOf() } /** @@ -714,7 +714,7 @@ object MmkvManager { */ fun decodeWebDavConfig(): WebDavConfig? { val json = mainStorage.decodeString(KEY_WEBDAV_CONFIG) ?: return null - return JsonUtil.fromJson(json, WebDavConfig::class.java) + return JsonUtil.fromJsonSafe(json, WebDavConfig::class.java) } //endregion diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt index 1ed42a53..ac0c4ca1 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt @@ -73,7 +73,7 @@ object SettingsManager { return null } - return JsonUtil.fromJson(assets, Array::class.java)?.toMutableList() + return JsonUtil.fromJsonSafe(assets, Array::class.java)?.toMutableList() } /** @@ -97,7 +97,7 @@ object SettingsManager { } try { - val rulesetList = JsonUtil.fromJson(content, Array::class.java)?.toMutableList() + val rulesetList = JsonUtil.fromJsonSafe(content, Array::class.java)?.toMutableList() if (rulesetList.isNullOrEmpty()) { return false } @@ -191,7 +191,7 @@ object SettingsManager { val config = decodeServerConfig(guid) ?: return false if (config.configType == EConfigType.CUSTOM) { val raw = MmkvManager.decodeServerRaw(guid) ?: return false - val v2rayConfig = JsonUtil.fromJson(raw, V2rayConfig::class.java) + val v2rayConfig = JsonUtil.fromJsonSafe(raw, V2rayConfig::class.java) val exist = v2rayConfig?.routing?.rules?.filter { it.outboundTag == TAG_DIRECT }?.any { it.domain?.contains(GEOSITE_PRIVATE) == true || it.ip?.contains(GEOIP_PRIVATE) == true } @@ -571,7 +571,7 @@ object SettingsManager { return } - val guids = JsonUtil.fromJson(oldJson, Array::class.java) ?: run { + val guids = JsonUtil.fromJsonSafe(oldJson, Array::class.java) ?: run { MmkvManager.encodeSettings(migrationKey, true) return } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt index 8cd9467e..2cdc0b55 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SpeedtestManager.kt @@ -98,7 +98,7 @@ object SpeedtestManager { proxyPassword = proxyPassword ) ) ?: return null - val ipInfo = JsonUtil.fromJson(content, IPAPIInfo::class.java) ?: return null + val ipInfo = JsonUtil.fromJsonSafe(content, IPAPIInfo::class.java) ?: return null val ip = listOf( ipInfo.ip, diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt index f498eb28..8fb9b4c5 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/UpdateCheckerManager.kt @@ -45,11 +45,11 @@ object UpdateCheckerManager { } val latestRelease = if (includePreRelease) { - JsonUtil.fromJson(response, Array::class.java) + JsonUtil.fromJsonSafe(response, Array::class.java) ?.firstOrNull() ?: throw IllegalStateException("No pre-release found") } else { - JsonUtil.fromJson(response, GitHubRelease::class.java) + JsonUtil.fromJsonSafe(response, GitHubRelease::class.java) } if (latestRelease == null) { return@withContext CheckUpdateResult(hasUpdate = false) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt index e779634f..88094475 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt @@ -35,6 +35,23 @@ object JsonUtil { return gson.fromJson(src, cls) } + /** + * Safely parses a JSON string into an object of the specified class. + * Returns null if parsing fails instead of throwing an exception. + * + * @param src The JSON string to parse. + * @param cls The class of the object to parse into. + * @return The parsed object, or null if parsing fails. + */ + fun fromJsonSafe(src: String, cls: Class): T? { + return try { + gson.fromJson(src, cls) + } catch (e: Exception) { + LogUtil.e(AppConfig.TAG, "Failed to parse JSON", e) + null + } + } + /** * Converts an object to its pretty-printed JSON representation. *