如何在Kotlin中解析JSON?

时间:2017-01-30 03:56:48

标签: java json kotlin

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

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

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

提前感谢您的帮助。本机上,我正在努力减少我需要的依赖项数量,如果答案仅用于JSON操作并解析它就足够了。

15 个答案:

答案 0 :(得分:35)

毫无疑问,在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")
}

答案 1 :(得分:32)

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

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

答案 2 :(得分:17)

没有外部库

解析这个:

val jsonString = """
    {
       "type":"Foo",
       "data":[
          {
             "id":1,
             "title":"Hello"
          },
          {
             "id":2,
             "title":"World"
          }
       ]
    }        
"""

使用这些类:

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")
}

用法:

val foos = Response(jsonString)

答案 3 :(得分:15)

不确定这是否是您所需要的,但这就是我的做法。

使用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
    }

以下是json的示例: {   “食物”:{     “FoodName”:“苹果”,     “重量”:“110”   } }

答案 4 :(得分:13)

您可以使用Gson

示例

第1步

添加编译

compile 'com.google.code.gson:gson:2.8.2'

第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
}

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
    )
}

第3步

使用Gson

var gson = Gson()
var mMineUserEntity = gson?.fromJson(response, MineUserEntity.MineUserInfo::class.java)

答案 5 :(得分:9)

我个人使用杰克逊模块作为Kotlin,你可以在这里找到:jackson-module-kotlin

implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$version"

作为一个例子,这里是解析流亡之路技能树的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 )

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

根据您的描述,我相信它符合您的需求。

答案 6 :(得分:3)

首先。

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

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

按照以下完整教程: Kotlin Android JSON Parsing Tutorial

如果你想手动解析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"
   }]
   """

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

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

答案 7 :(得分:2)

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

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

plugin

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

enter image description here

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

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

答案 8 :(得分:2)

这与Elisha's answer一样使用kotlinx.serialization。同时,针对即将发布的1.0版本,该API处于稳定状态。请注意,例如JSON.parse已重命名为Json.parse,现在为Json.decodeFromString。从Kotlin 1.4.0开始,它也被导入gradle differently中:

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC"
}
apply plugin: 'kotlinx-serialization'

用法示例:

@Serializable
data class Properties(val nid: Int, val tid: Int)
@Serializable
data class Feature(val pos: List<Double>, val properties: Properties? = null, 
    val count: Int? = null)
@Serializable
data class Root(val features: List<Feature>)


val root = Json.decodeFromString<Root>(jsonStr)
val rootAlt = Json.decodeFromString(Root.serializer(), jsonStr)  // equivalent

val str = Json.encodeToString(root)  // type 'Root' can be inferred!

// For a *top-level* list (does not apply in my case) you would use 
val fList = Json.decodeFromString<List<Feature>>(jsonStr)
val fListAlt = Json.decodeFromString(ListSerializer(Feature.serializer()), jsonStr)

Kotlin的data class定义了一个主要包含数据的类,并自动定义了.toString()和其他方法(例如,解构声明)。我在此处将空值(?)类型用于可选字段。

答案 9 :(得分:1)

http://www.jsonschema2pojo.org/   嗨,您可以使用此网站将json转换为pojo。
  control + Alt + shift + k

之后,您可以手动将该模型类转换为kotlin模型类。借助上述快捷方式。

答案 10 :(得分:1)

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

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

dependencies {
   implementation 'com.google.code.gson:gson:2.8.6'
}

2。现在,您需要将JSON转换为Kotlin Data类:

复制您的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)

完成:)

答案 11 :(得分:0)

Kotin序列化

Jetbrains的Kotlin特定库,用于所有受支持的平台– Android,JVM,JavaScript,本机

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

莫希

Moshi是Square提供的适用于Android和Java的JSON库。

https://github.com/square/moshi

杰克逊

https://github.com/FasterXML/jackson

Gson

最受欢迎但几乎 已弃用

https://github.com/google/gson

JSON到Java

http://www.jsonschema2pojo.org/

JSON到Kotlin

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

答案 12 :(得分:0)

我在kotlin中使用自定义实现:

/**
 * Created by Anton Kogan on 10/9/2020
 */
object JsonParser {

    val TAG = "JsonParser"
    /**
 * parse json object
 * @param objJson
 * @param include - all  keys, that you want to display
 * @return  Map<String, String>
 * @throws JSONException
 */
    @Throws(JSONException::class)
    fun parseJson(objJson: Any?, map :HashMap<String, String>, include : Array<String>?): Map<String, String> {
        // If obj is a json array
        if (objJson is JSONArray) {
            for (i in 0 until objJson.length()) {
                parseJson(objJson[i], map, include)
            }
        } else if (objJson is JSONObject) {
            val it: Iterator<*> = objJson.keys()
            while (it.hasNext()) {
                val key = it.next().toString()
                // If you get an array
                when (val jobject = objJson[key]) {
                    is JSONArray -> {
                        Log.e(TAG, " JSONArray: $jobject")
                        parseJson(
                            jobject, map, include
                        )
                    }
                    is JSONObject -> {
                        Log.e(TAG, " JSONObject: $jobject")
                        parseJson(
                            jobject, map, include
                        )
                    }
                    else -> {
//
                        if(include == null || include.contains(key)) // here is check for include param
                        {
                            map[key] = jobject.toString()
                            Log.e(TAG, " adding to map: $key $jobject")
                        }
                    }
                }
            }
        }
        return map
    }

    /**
     * parse json object
     * @param objJson
     * @param include - all  keys, that you want to display
     * @return  Map<String, String>
     * @throws JSONException
     */
    @Throws(JSONException::class)
    fun parseJson(objJson: Any?, map :HashMap<String, String>): Map<String, String> {
        return parseJson(objJson, map, null)
    }
}

您可以像这样使用它:

    val include= arrayOf(
        "atHome",//JSONArray
        "cat",
        "dog",
        "persons",//JSONArray
        "man",
        "woman"
    )
    JsonParser.parseJson(jsonObject, map, include)
    val linearContent: LinearLayout = taskInfoFragmentBinding.infoContainer

以下是一些有用的链接:

json解析:

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

从json创建POJO: https://codebeautify.org/jsonviewer

改造: https://square.github.io/retrofit/

Gson: https://github.com/google/gson

答案 13 :(得分:-1)

有点晚了,但是随便吧。

如果您喜欢将JSON解析为JavaScript(例如使用Kotlin语义的构造),建议使用JSONKraken,我是作者。

对此事的建议和见解很准确!

答案 14 :(得分:-3)

从此处下载deme源(Json parsing in android kotlin

添加此依赖项:

compile 'com.squareup.okhttp3:okhttp:3.8.1'

调用api函数:

 fun run(url: String) {
    dialog.show()
    val request = Request.Builder()
            .url(url)
            .build()

    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            dialog.dismiss()

        }

        override fun onResponse(call: Call, response: Response) {
            var str_response = response.body()!!.string()
            val json_contact:JSONObject = JSONObject(str_response)

            var jsonarray_contacts:JSONArray= json_contact.getJSONArray("contacts")

            var i:Int = 0
            var size:Int = jsonarray_contacts.length()

            al_details= ArrayList();

            for (i in 0.. size-1) {
                var json_objectdetail:JSONObject=jsonarray_contacts.getJSONObject(i)


                var model:Model= Model();
                model.id=json_objectdetail.getString("id")
                model.name=json_objectdetail.getString("name")
                model.email=json_objectdetail.getString("email")
                model.address=json_objectdetail.getString("address")
                model.gender=json_objectdetail.getString("gender")

                al_details.add(model)


            }

            runOnUiThread {
                //stuff that updates ui
                val obj_adapter : CustomAdapter
                obj_adapter = CustomAdapter(applicationContext,al_details)
                lv_details.adapter=obj_adapter
            }

            dialog.dismiss()

        }

    })