最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Kotlin Multi platform Long Decimal Decoding fails - Stack Overflow

programmeradmin1浏览0评论

Kotlin Multi platform - Decoding fails - with Double with more decimals { "Test": [0.1, 0.01, 0.001, 0.0001, 0.0001] }

Note: The challenge is not in Kotlin alone. The change is with Kotlin Multi Platform, all the the libraries available in Kotlin are not available in KMP

0.0001 return 1.0E-4 it returns ok up to 0.001

CODE

import kotlinx.serialization.*
import kotlinx.serialization.json.*

fun convertToJsonString(inputMap: Map<String, Any>): String {
    // Recursively traverse the map to handle any structure
    fun traverseMap(value: Any): JsonElement {
        return when (value) {
            is Map<*, *> -> {
                // Handle nested Map
                val newObject = JsonObject(
                    value.filter { it is Map.Entry<*, *> && it.key is String } // Filter valid map entries
                        .map { it as Map.Entry<String, Any> } // Safely cast to Map.Entry<String, Any>
                        .associate { it.key to traverseMap(it.value) }
                )
                newObject
            }
            is List<*> -> {
                // Handle List
                JsonArray(value.map { traverseMap(it!!) })
            }
            is Number -> {
                // For primitive types, return as JsonPrimitive
                JsonPrimitive(value)
            }
            is String, is Number, is Boolean -> {
                // For primitive types, return as JsonPrimitive
                JsonPrimitive(value.toString())
            }
            else -> {
                // Handle any other cases, potentially throw an exception or handle
                throw IllegalArgumentException("Unsupported value type")
            }
        }
    }

    // Process the map recursively
    val processedJson = JsonObject(inputMap.mapValues { traverseMap(it.value) })

    // Convert the processed JSON back to a JSON string and return
    return Json.encodeToString(processedJson)
}

fun main() {
    // Input JSON (directly as a JsonElement)
    val map = mapOf(
    "test" to listOf(
        0.1, 
        0.01,
        0.001,
        0.0001,
        0.00001,
        0.12345,
        0.123456789,
        0.123467890123,
        0.0000012345,
    )
)

    // Call the function with the input JSON element
    val outputJsonString = convertToJsonString(map)

    // Print the resulting JSON string
    println(outputJsonString)
}

Kotlin Multi platform - Decoding fails - with Double with more decimals { "Test": [0.1, 0.01, 0.001, 0.0001, 0.0001] }

Note: The challenge is not in Kotlin alone. The change is with Kotlin Multi Platform, all the the libraries available in Kotlin are not available in KMP

0.0001 return 1.0E-4 it returns ok up to 0.001

CODE

import kotlinx.serialization.*
import kotlinx.serialization.json.*

fun convertToJsonString(inputMap: Map<String, Any>): String {
    // Recursively traverse the map to handle any structure
    fun traverseMap(value: Any): JsonElement {
        return when (value) {
            is Map<*, *> -> {
                // Handle nested Map
                val newObject = JsonObject(
                    value.filter { it is Map.Entry<*, *> && it.key is String } // Filter valid map entries
                        .map { it as Map.Entry<String, Any> } // Safely cast to Map.Entry<String, Any>
                        .associate { it.key to traverseMap(it.value) }
                )
                newObject
            }
            is List<*> -> {
                // Handle List
                JsonArray(value.map { traverseMap(it!!) })
            }
            is Number -> {
                // For primitive types, return as JsonPrimitive
                JsonPrimitive(value)
            }
            is String, is Number, is Boolean -> {
                // For primitive types, return as JsonPrimitive
                JsonPrimitive(value.toString())
            }
            else -> {
                // Handle any other cases, potentially throw an exception or handle
                throw IllegalArgumentException("Unsupported value type")
            }
        }
    }

    // Process the map recursively
    val processedJson = JsonObject(inputMap.mapValues { traverseMap(it.value) })

    // Convert the processed JSON back to a JSON string and return
    return Json.encodeToString(processedJson)
}

fun main() {
    // Input JSON (directly as a JsonElement)
    val map = mapOf(
    "test" to listOf(
        0.1, 
        0.01,
        0.001,
        0.0001,
        0.00001,
        0.12345,
        0.123456789,
        0.123467890123,
        0.0000012345,
    )
)

    // Call the function with the input JSON element
    val outputJsonString = convertToJsonString(map)

    // Print the resulting JSON string
    println(outputJsonString)
}

{"test":[0.1,0.01,0.001,1.0E-4,1.0E-5,0.12345,0.123456789,0.123467890123,1.2345E-6]}

Share Improve this question edited 2 days ago yarlg asked Apr 1 at 10:30 yarlgyarlg 3,6613 gold badges22 silver badges20 bronze badges 1
  • Those are correct representations of those numbers. The resulting JSON is actually valid JSON because JSON supports for example 1.0E-4 as number. see also stackoverflow/questions/13617818/json-e-and-json-e – Ivo Commented Apr 1 at 10:57
Add a comment  | 

1 Answer 1

Reset to default 2

Scientific/exponential notation is a valid way to represent decimal numbers.
Clients of your API or server consuming your requests should be able to handle it.

But if you still prefer to avoid scientific notation (do not have E-n), I see 2 options

  1. Convert numeric value to BigDecimal and then to string using .toPlainString()
  2. Convert to string using String.format, but precision at some point is lost

After conversion to string, use JsonUnquotedLiteral to have primitive value without surrounding it in quotes.
JsonUnquotedLiteral is an experimental kotlinx.serialization API, so mark the code that uses it with @OptIn(ExperimentalSerializationApi::class)

  1. BigDecimal approach
is Number -> {
    JsonUnquotedLiteral(
        BigDecimal(value.toString())
            .stripTrailingZeros()
            .toPlainString()
    )
}
  1. String formatting approach
is Double, is Float -> {
    JsonUnquotedLiteral(String.format("%.20f", value).trimEnd('0'))
}

I guess having a BigDecimal substitute across all platforms is a problem, but hopefully using String.format should be easier.

发布评论

评论列表(0)

  1. 暂无评论