使用ktor初始化可以是JsonPrimitive或JsonArray的值

wfsdck30  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(150)

我在我的项目中使用Ktor来进行格式化。我有一个json对象,它包含一个动态的value-field,我不太确定如何处理它。下面是一些值的例子:

"value":["test","rest"]
------------------------
"value":"test"
------------------------
"value":true

字符串
有什么建议能让我更好地处理这事吗?

50few1ms

50few1ms1#

您可以将其表示为String值的列表,但在这种情况下,没有办法区分truefalse值。如果您只需要在一个地方得到结果,则可以在那里内联以下代码。

val client = HttpClient(OkHttp) {
    install(ContentNegotiation) {
        json()
    }
}

val response = client.get("/")
val obj = response.body<JsonObject>()

val values: List<String> = when(val json = obj["value"]) {
    is JsonPrimitive -> {
        when {
            json.isString -> listOf(json.toString()) // JSON string is a list with a single value
            json.booleanOrNull != null -> emptyList() // JSON boolean is an empty list
            else -> error("Expected a string or boolean")
        }
    }

    is JsonArray -> json.map { el -> // JSON array is a list of strings
        if (el is JsonPrimitive && el.isString) {
            el.toString()
        } else {
            error("Expected an array of strings")
        }
    }

    else -> error("Expected an array or primitive value")
}

println(values)

字符串

xkrw2x1b

xkrw2x1b2#

我找到了一个使用Jackson的解决方案(我相信它可以用类似的方式用kotlinx-serialization & gson来完成)。
首先让ObjectMapper示例使用你提供给ktor应用程序的相同设置(也许可以通过调用示例获得,但我不知道):

lateinit var JacksonObjectMapper: ObjectMapper
fun Application.configureJsonSerialization() {
  install(ContentNegotiation) {
  // install Jackson serialization
  jackson {
    // HERE we get ObjectMapper instance to use it later
    JacksonObjectMapper = this
    // ... other jackson config ...
  }
}

字符串
然后使用它:

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.module.kotlin.treeToValue
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

fun Application.configureJacksonTestRoute() {
  routing {
      post("/test/json/dynamic-object"){
      val rootObj = call.receive<JsonNode>()
      
      var stringArrayValue: List<String>? = null
      var booleanValue: Boolean? = null
      var stringValue: String? = null
      
      if (rootObj.has("value"))
        rootObj["value"].let {
          // HERE we give a class (List<String>) 
          // to object mapper
          if (it.isArray) stringArrayValue = 
          JacksonObjectMapper.treeToValue<List<String>>(it)
          else if (it.isBoolean) booleanValue = it.asBoolean()
          else if (it.isTextual) stringValue = it.asText()
        }
    
       call.respond("ok")
     }
   }
 }

相关问题