Keep fractional numbers when saving JSON array subscriptions (#6293)

* Keep fractional numbers when saving JSON array subscriptions

toJsonPretty wrote every Double through toInt(), so 0.4 became 0 and
values above Int.MAX_VALUE were clamped. Write whole numbers as Long
and leave other values as Double.

Fixes #6291

* Add a JsonUtil test for numbers in config arrays

* Update JsonUtil.kt

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
This commit is contained in:
JaroWorldand2dust authored and GitHub committed 2026-10-06 14:41:29 +08:00
1 parent a4dd3d08de
commit fcacb9cfb0
2 files changed
+31 -3

No files matched your search

@@ -7,6 +7,7 @@ import com.google.gson.JsonParser
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.ToNumberPolicy
import com.google.gson.reflect.TypeToken
import com.v2ray.ang.AppConfig
import java.lang.reflect.Type
@@ -64,12 +65,15 @@ object JsonUtil {
val gsonPre = GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.registerTypeAdapter( // custom serializer is needed here since JSON by default parse number as Double, core will fail to start
object : TypeToken<Double>() {}.type,
JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? ->
JsonPrimitive(
src?.toInt()
)
when (src) {
null -> null
src.toLong().toDouble() -> JsonPrimitive(src.toLong())
else -> JsonPrimitive(src)
}
}
)
.create()
@@ -0,0 +1,24 @@
package com.v2ray.ang.util
import com.google.gson.JsonParser
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class JsonUtilTest {
@Test
fun toJsonPrettyKeepsNumbersOfConfigArrayElements() {
val configs = JsonUtil.fromJson(
"""[{"port":443,"tolerance":0.4,"offset":-0.5,"timestamp":1700000000000,"name":"0.4"}]""",
Array<Any>::class.java
)
val output = JsonParser.parseString(JsonUtil.toJsonPretty(configs!![0])).asJsonObject
assertEquals("443", output["port"].asString)
assertEquals("0.4", output["tolerance"].asString)
assertEquals("-0.5", output["offset"].asString)
assertEquals("1700000000000", output["timestamp"].asString)
assertEquals("0.4", output["name"].asString)
}
}