如何在Kotlin中解析JSON?

AJ_*_*310 79 java json kotlin

我从服务中收到一个非常深的JSON对象字符串,我必须将其解析为JSON对象,然后将其映射到类.

如何在Kotlin中将JSON字符串转换为对象?

在那之后映射到各个类,我使用了Jackson的StdDeserializer.问题出现在对象具有也必须被反序列化为类的属性的时刻.我无法在另一个反序列化器中获取对象映射器,至少我不知道如何.

在此先感谢您的帮助.优选地,本机地,我正在尝试减少我需要的依赖项的数量,所以如果答案仅用于JSON操作并且解析它就足够了.

Eli*_*old 77

毫无疑问,在Kotlin中解析的未来将与kotlinx.serialization一起使用.它是Kotlin图书馆的一部分.它还处于孵化阶段的写作阶段.

https://github.com/Kotlin/kotlinx.serialization

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

@Serializable
data class MyModel(val a: Int, @Optional val b: String = "42")

fun main(args: Array<String>) {

    // serializing objects
    val jsonData = JSON.stringify(MyModel.serializer(), MyModel(42))
    println(jsonData) // {"a": 42, "b": "42"}

    // serializing lists
    val jsonList = JSON.stringify(MyModel.serializer().list, listOf(MyModel(42)))
    println(jsonList) // [{"a": 42, "b": "42"}]

    // parsing data back
    val obj = JSON.parse(MyModel.serializer(), """{"a":42}""")
    println(obj) // MyModel(a=42, b="42")
}
Run Code Online (Sandbox Code Playgroud)

  • 1.0终于出来了!这里有相同的示例:https://blog.jetbrains.com/kotlin/2020/10/kotlinx-serialization-1-0-released/ (6认同)
  • KotlinX 序列化仍处于实验阶段,因此他们在新版本中引入了重大更改。此外,它不是线程安全的,因此如果多个线程尝试使用“Json”的单个实例(这很常见),您的 JSON 可能会被损坏。此外,Github 上还存在几个带有 bug 标签的开放问题。因此,我想说,在生产中使用它仍然存在风险(除非您愿意花时间修复潜在问题并且不打算频繁更新)。该项目确实很有趣,尤其是对于 Kotlin 多平台项目来说,但它还不稳定。 (5认同)
  • 我遇到的问题是你很难将它与泛型一起使用。至少我还没有弄清楚该怎么做。我当然不想使用反射。 (3认同)

Jas*_*rne 49

您可以使用此库 https://github.com/cbeust/klaxon

Klaxon是一个轻量级的库,用于在Kotlin中解析JSON.

  • 作者在这里,如果您有任何问题/建议,请随时给我发电子邮件. (53认同)
  • 为什么我们需要第三方库来解析JSON? (2认同)

fro*_*ouo 20

没有外部库

解析这个:

val jsonString = """
    {
       "type":"Foo",
       "data":[
          {
             "id":1,
             "title":"Hello"
          },
          {
             "id":2,
             "title":"World"
          }
       ]
    }        
"""
Run Code Online (Sandbox Code Playgroud)

使用这些类:

import org.json.JSONObject

class Response(json: String) : JSONObject(json) {
    val type: String? = this.optString("type")
    val data = this.optJSONArray("data")
            ?.let { 0.until(it.length()).map { i -> it.optJSONObject(i) } } // returns an array of JSONObject
            ?.map { Foo(it.toString()) } // transforms each JSONObject of the array into Foo
}

class Foo(json: String) : JSONObject(json) {
    val id = this.optInt("id")
    val title: String? = this.optString("title")
}
Run Code Online (Sandbox Code Playgroud)

用法:

val foos = Response(jsonString)
Run Code Online (Sandbox Code Playgroud)

  • 因此,如果这不需要任何外部库,那应该意味着 org.json.JSONObject 是标准库的一部分,对吧? (4认同)
  • @still_dreaming_1 是的,“在 API 级别 1 中添加”,参见。https://developer.android.com/reference/org/json/JSONObject.html (2认同)
  • 我猜这是安卓的事?我在 JVM 的 Kotlin 或 Java 标准库中寻找它。 (2认同)

mar*_*rkB 18

不确定这是否是你需要的,但这就是我做的.

使用import org.json.JSONObject:

    val jsonObj = JSONObject(json.substring(json.indexOf("{"), json.lastIndexOf("}") + 1))
    val foodJson = jsonObj.getJSONArray("Foods")
    for (i in 0..foodJson!!.length() - 1) {
        val categories = FoodCategoryObject()
        val name = foodJson.getJSONObject(i).getString("FoodName")
        categories.name = name
    }
Run Code Online (Sandbox Code Playgroud)

以下是json的样本:{"Foods":{"FoodName":"Apples","Weight":"110"}}

  • 什么是依赖? (7认同)
  • @LuísSoares这就是我使用的https://mvnrepository.com/artifact/org.json/json (2认同)
  • 我使用了 org.json。这是链接:https://mvnrepository.com/artifact/org.json/json/20180813 (2认同)

KeL*_*yue 17

你可以用Gson.

步骤1

添加编译

compile 'com.google.code.gson:gson:2.8.2'
Run Code Online (Sandbox Code Playgroud)

第2步

将json转换为Kotlin Bean(使用JsonToKotlinClass)

像这样

Json 数据

{
"timestamp": "2018-02-13 15:45:45",
"code": "OK",
"message": "user info",
"path": "/user/info",
"data": {
    "userId": 8,
    "avatar": "/uploads/image/20180115/1516009286213053126.jpeg",
    "nickname": "",
    "gender": 0,
    "birthday": 1525968000000,
    "age": 0,
    "province": "",
    "city": "",
    "district": "",
    "workStatus": "Student",
    "userType": 0
},
"errorDetail": null
}
Run Code Online (Sandbox Code Playgroud)

Kotlin Bean

class MineUserEntity {

    data class MineUserInfo(
        val timestamp: String,
        val code: String,
        val message: String,
        val path: String,
        val data: Data,
        val errorDetail: Any
    )

    data class Data(
        val userId: Int,
        val avatar: String,
        val nickname: String,
        val gender: Int,
        val birthday: Long,
        val age: Int,
        val province: String,
        val city: String,
        val district: String,
        val workStatus: String,
        val userType: Int
    )
}
Run Code Online (Sandbox Code Playgroud)

第3步

使用 Gson

var gson = Gson()
var mMineUserEntity = gson?.fromJson(response, MineUserEntity.MineUserInfo::class.java)
Run Code Online (Sandbox Code Playgroud)

  • Gson 的问题在于它忽略了可空性。如果 JSON 中缺少“val”属性,则该属性很容易为“null”。此外,根本不使用默认值。 (2认同)

xjc*_*jcl 13

这就像以利沙的答案kotlinx.serialization一样。同时该项目已经过了 1.0 版本,因此 API 已经发生了变化。请注意,eg已重命名为。从 Kotlin 1.4.0 开始,它在 gradle 中的导入方式也有所不同:JSON.parseJson.decodeFromString

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0"
}
apply plugin: 'kotlinx-serialization'
Run Code Online (Sandbox Code Playgroud)

用法示例:

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0"
}
apply plugin: 'kotlinx-serialization'
Run Code Online (Sandbox Code Playgroud)
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
Run Code Online (Sandbox Code Playgroud)

您可以对可为空字段和可选字段T?使用可为空类型 () :

@Serializable
data class Point(val x: Int, val y: Int)

val pt = Json.decodeFromString<Point>("""{"y": 1, "x": 2}""")
val str = Json.encodeToString(pt)  // type can be inferred!

val ilist = Json.decodeFromString<List<Int>>("[-1, -2]")
val ptlist = Json.decodeFromString<List<Point>>(
    """[{"x": 3, "y": 4}, {"x": 5, "y": 6}]"""
)
Run Code Online (Sandbox Code Playgroud)

Kotlin 的data class类主要保存数据并具有成员,.toString()以及自动定义的其他方法(例如解构声明)。


小智 11

我个人使用Jackson模块进行Kotlin,你可以在这里找到:jackson-module-kotlin.

implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$version"
Run Code Online (Sandbox Code Playgroud)

作为一个例子,这里是解析流亡之路技能树的JSON的代码,它非常重(格式化时为84k行):

Kotlin代码:

package util

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.*
import java.io.File

data class SkillTreeData( val characterData: Map<String, CharacterData>, val groups: Map<String, Group>, val root: Root,
                          val nodes: List<Node>, val extraImages: Map<String, ExtraImage>, val min_x: Double,
                          val min_y: Double, val max_x: Double, val max_y: Double,
                          val assets: Map<String, Map<String, String>>, val constants: Constants, val imageRoot: String,
                          val skillSprites: SkillSprites, val imageZoomLevels: List<Int> )


data class CharacterData( val base_str: Int, val base_dex: Int, val base_int: Int )

data class Group( val x: Double, val y: Double, val oo: Map<String, Boolean>?, val n: List<Int> )

data class Root( val g: Int, val o: Int, val oidx: Int, val sa: Int, val da: Int, val ia: Int, val out: List<Int> )

data class Node( val id: Int, val icon: String, val ks: Boolean, val not: Boolean, val dn: String, val m: Boolean,
                 val isJewelSocket: Boolean, val isMultipleChoice: Boolean, val isMultipleChoiceOption: Boolean,
                 val passivePointsGranted: Int, val flavourText: List<String>?, val ascendancyName: String?,
                 val isAscendancyStart: Boolean?, val reminderText: List<String>?, val spc: List<Int>, val sd: List<String>,
                 val g: Int, val o: Int, val oidx: Int, val sa: Int, val da: Int, val ia: Int, val out: List<Int> )

data class ExtraImage( val x: Double, val y: Double, val image: String )

data class Constants( val classes: Map<String, Int>, val characterAttributes: Map<String, Int>,
                      val PSSCentreInnerRadius: Int )

data class SubSpriteCoords( val x: Int, val y: Int, val w: Int, val h: Int )

data class Sprite( val filename: String, val coords: Map<String, SubSpriteCoords> )

data class SkillSprites( val normalActive: List<Sprite>, val notableActive: List<Sprite>,
                         val keystoneActive: List<Sprite>, val normalInactive: List<Sprite>,
                         val notableInactive: List<Sprite>, val keystoneInactive: List<Sprite>,
                         val mastery: List<Sprite> )

private fun convert( jsonFile: File ) {
    val mapper = jacksonObjectMapper()
    mapper.configure( DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true )

    val skillTreeData = mapper.readValue<SkillTreeData>( jsonFile )
    println("Conversion finished !")
}

fun main( args : Array<String> ) {
    val jsonFile: File = File( """rawSkilltree.json""" )
    convert( jsonFile )
Run Code Online (Sandbox Code Playgroud)

JSON(未格式化):http://filebin.ca/3B3reNQf3KXJ/rawSkilltree.json

鉴于您的描述,我相信它符合您的需求.


Tou*_*hid 10

GSON 是 Android 和 Web 平台在 Kotlin 项目中解析 JSON 的不错选择。该库由 Google 开发。 https://github.com/google/gson

1. 首先,将 GSON 添加到您的项目中:

dependencies {
    implementation 'com.google.code.gson:gson:2.8.9'
}
Run Code Online (Sandbox Code Playgroud)

2. 现在您需要将 JSON 转换为 Kotlin 数据类:

复制您的 JSON 并转到此 ( https://json2kt.com ) 网站并将您的 JSON 粘贴到输入 Json 框中。在适当的框中写入包(例如:com.example.appName)和类名称(例如:UserData)。该网站将在下面显示您的数据类的实时预览,您也可以一次性下载所有类的 zip 文件。

下载所有类后,解压 zip 文件并将它们放入您的项目中。

3. 现在解析如下:

val myJson = """
{
    "user_name": "john123",
    "email": "john@example.com",
    "name": "John Doe"
}
""".trimIndent()

val gson = Gson()
var mUser = gson.fromJson(myJson, UserData::class.java)
println(mUser.userName)
Run Code Online (Sandbox Code Playgroud)

完毕 :)


Dev*_*ine 7

首先。

您可以在 Android Studio 中使用 JSON 到 Kotlin 数据类转换器插件将 JSON 映射到 POJO 类(kotlin 数据类)。该插件将根据 JSON 注释您的 Kotlin 数据类。

然后你可以使用 GSON 转换器将 JSON 转换为 Kotlin。

请遵循此完整教程: Kotlin Android JSON 解析教程

如果你想手动解析json。

val **sampleJson** = """
  [
  {
   "userId": 1,
   "id": 1,
   "title": "sunt aut facere repellat provident occaecati excepturi optio 
    reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita"
   }]
   """
Run Code Online (Sandbox Code Playgroud)

解析上面的 JSON 数组及其索引 0 处的对象的代码。

var jsonArray = JSONArray(sampleJson)
for (jsonIndex in 0..(jsonArray.length() - 1)) {
Log.d("JSON", jsonArray.getJSONObject(jsonIndex).getString("title"))
}
Run Code Online (Sandbox Code Playgroud)


Coo*_*ind 5

要将JSON转换为Kotlin,请使用http://www.json2kotlin.com/

您也可以使用Android Studio插件。文件>设置,Plugins在左树中选择,按“浏览存储库...”,搜索“ JsonToKotlinClass ”,选择它并单击绿色按钮“安装”。

插入

AS重新启动后,即可使用它。您可以使用创建类File > New > JSON To Kotlin Class (JsonToKotlinClass)。另一种方法是按Alt +K。

在此处输入图片说明

然后,您将看到一个粘贴JSON的对话框。

在2018年,我不得不package com.my.package_name在课程开始时添加。


iam*_*sal 5

Kotlin 序列化

\n

JetBrains 的 Kotlin 特定库,适用于所有支持的平台 \xe2\x80\x93 Android、JVM、JavaScript、Native。

\n

https://github.com/Kotlin/kotlinx.serialization

\n

莫希

\n

Moshi 是 Square 开发的适用于 Android 和 Java 的 JSON 库。

\n

https://github.com/square/moshi

\n

杰克逊

\n

https://github.com/FasterXML/jackson

\n

格森

\n

最受欢迎但几乎已被弃用

\n

https://github.com/google/gson

\n

JSON 到 Java

\n

http://www.jsonschema2pojo.org/

\n

JSON 到 Kotlin

\n

IntelliJ 插件 - https://plugins.jetbrains.com/plugin/9960-json-to-kotlin-class-jsontokotlinclass-

\n