简体   繁体   English

如何解析 Kotlin 中的 JSON?

[英]How to parse JSON in Kotlin?

I'm receiving a quite deep JSON object string from a service which I must parse to a JSON object and then map it to classes. I'm receiving a quite deep JSON object string from a service which I must parse to a JSON object and then map it to classes.

How can I transform a JSON string to object in Kotlin?如何在 Kotlin 中将 JSON 字符串转换为 object?

After that the mapping to the respective classes, I was using StdDeserializer from Jackson.在映射到各个类之后,我使用了来自 Jackson 的 StdDeserializer。 The problem arises at the moment the object had properties that also had to be deserialized into classes.问题出现在 object 具有也必须反序列化为类的属性时。 I was not able to get the object mapper, at least I didn't know how, inside another deserializer.我无法在另一个解串器中获得 object 映射器,至少我不知道如何。

Preferably, natively, I'm trying to reduce the number of dependencies I need so if the answer is only for JSON manipulation and parsing it'd be enough.最好,在本地,我试图减少我需要的依赖项的数量,所以如果答案仅适用于 JSON 操作和解析就足够了。

There is no question that the future of parsing in Kotlin will be with kotlinx.serialization.毫无疑问,Kotlin 解析的未来将是 kotlinx.serialization。 It is part of Kotlin libraries.它是 Kotlin 库的一部分。 Version kotlinx.serialization 1.0 is finally released kotlinx.serialization 1.0 版本终于发布了

https://github.com/Kotlin/kotlinx.serialization 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")
}

You can use this library https://github.com/cbeust/klaxon你可以使用这个库https://github.com/cbeust/klaxon

Klaxon is a lightweight library to parse JSON in Kotlin. Klaxon 是一个在 Kotlin 中解析 JSON 的轻量级库。

Without external library (on Android)没有外部库(在 Android 上)

To parse this:要解析这个:

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

Use these classes:使用这些类:

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

Usage:用法:

val foos = Response(jsonString)

You can use Gson .您可以使用Gson

Example例子

Step 1步骤1

Add compile添加编译

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

Step 2第2步

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

Like this像这样

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

Step 3第 3 步

Use Gson使用Gson

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

Not sure if this is what you need but this is how I did it.不确定这是否是您需要的,但我就是这样做的。

Using import org.json.JSONObject :使用导入 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
    }

Here's a sample of the json :这是 json 的示例:

{"Foods": [{"FoodName": "Apples","Weight": "110" } ]} {“食物”:[{“食物名称”:“苹果”,“重量”:“110”}]}

I personally use the Jackson module for Kotlin that you can find here: jackson-module-kotlin .我个人使用 Kotlin 的 Jackson 模块,您可以在这里找到: jackson-module-kotlin

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

As an example, here is the code to parse the JSON of the Path of Exile skilltree which is quite heavy (84k lines when formatted) :例如,这里是解析流放之路技能树的 JSON 的代码,它非常重(格式化时为 84k 行):

Kotlin code:科特林代码:

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 (not-formatted): http://filebin.ca/3B3reNQf3KXJ/rawSkilltree.json JSON(未格式化):http: //filebin.ca/3B3reNQf3KXJ/rawSkilltree.json

Given your description, I believe it matches your needs.根据您的描述,我相信它符合您的需求。

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

Also you can use Android Studio plugin.您也可以使用 Android Studio 插件。 File > Settings, select Plugins in left tree, press "Browse repositories...", search " JsonToKotlinClass ", select it and click green button "Install".文件 > 设置,选择左侧树中的Plugins ,按“浏览存储库...”,搜索“ JsonToKotlinClass ”,选择它并单击绿色按钮“安装”。

插入

After AS restart you can use it. AS重启后就可以使用了。 You can create a class with File > New > JSON To Kotlin Class (JsonToKotlinClass) .您可以使用File > New > JSON To Kotlin Class (JsonToKotlinClass)创建一个类。 Another way is to press Alt + K.另一种方法是按 Alt + K。

在此处输入图像描述

Then you will see a dialog to paste JSON.然后你会看到一个粘贴 JSON 的对话框。

In 2018 I had to add package com.my.package_name at the beginning of a class.在 2018 年,我不得不在课程的开头添加package com.my.package_name

This uses kotlinx.serialization like Elisha's answer .这使用kotlinx.serialization就像以利沙的回答一样。 Meanwhile the project is past version 1.0 so the API has changed.同时,该项目已超过 1.0 版,因此 API 已更改。 Note that eg JSON.parse was renamed to Json.decodeFromString .请注意,例如JSON.parse已重命名为Json.decodeFromString Also it is imported in gradle differently starting in Kotlin 1.4.0:从 Kotlin 1.4.0 开始,它也以不同的方式导入 gradle:

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0"
}
apply plugin: 'kotlinx-serialization'

Example usage:示例用法:

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@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}]"""
)

You can use nullable types ( T? ) for both nullable and optional fields :您可以对可空字段和可选字段使用可空类型 ( T? ):

@Serializable
data class Point2(val x: Int, val y: Int? = null)

val nlist = Json.decodeFromString<List<Point2>>(
    """[{"x": 7}, {"x": 8, "y": null}, {"x": 9, "y": 0}]"""
)

Kotlin's data class is a class that mainly holds data and has members, .toString() and other methods (eg destructuring declarations) automatically defined. Kotlin 的data class是一个主要保存数据并自动定义了成员、 .toString()和其他方法(例如解构声明)的类。

GSON is a good choice for Android and Web platform to parse JSON in a Kotlin project. GSON 是 Android 和 Web 平台在 Kotlin 项目中解析 JSON 的不错选择。 This library is developed by Google.这个库是由谷歌开发的。 https://github.com/google/gson https://github.com/google/gson

1. First add GSON to your project: 1.首先将GSON添加到您的项目中:

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

2. Now you need to convert your JSON to Kotlin Data class: 2. 现在您需要将您的 JSON 转换为 Kotlin 数据类:

Copy your JSON and go to this( https://json2kt.com ) website and paste your JSON to Input Json box.复制您的 JSON 并转到此( https://json2kt.com )网站并将您的 JSON 粘贴到 Input Json 框中。 Write package(ex: com.example.appName) and Class name(ex: UserData) in proper box.在适当的框中写入包(例如:com.example.appName)和类名(例如:UserData)。 This site will show live preview of your data class below and also you can download all classes at once in a zip file.该站点将在下面显示您的数据类的实时预览,您也可以一次下载所有类的 zip 文件。

After downloading all classes extract zip file & place them into your project.下载所有类后提取 zip 文件并将它们放入您的项目中。

3. Now Parse like below: 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)

Done :)完毕 :)

First of all.首先。

You can use JSON to Kotlin Data class converter plugin in Android Studio for JSON mapping to POJO classes (kotlin data class).您可以在 Android Studio 中使用 JSON to Kotlin Data 类转换器插件将 JSON 映射到 POJO 类(kotlin 数据类)。 This plugin will annotate your Kotlin data class according to JSON.此插件将根据 JSON 注释您的 Kotlin 数据类。

Then you can use GSON converter to convert JSON to Kotlin.然后您可以使用 GSON 转换器将 JSON 转换为 Kotlin。

Follow this Complete tutorial: Kotlin Android JSON Parsing Tutorial遵循这个完整的教程: Kotlin Android JSON Parsing Tutorial

If you want to parse json manually.如果你想手动解析 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"
   }]
   """

Code to Parse above JSON Array and its object at index 0.在 JSON 数组及其索引 0 处解析的代码。

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

A bit late, but whatever.有点晚了,但无论如何。

If you prefer parsing JSON to JavaScript-like constructs making use of Kotlin syntax, I recommend JSONKraken , of which I am the author.如果您更喜欢将 JSON 解析为使用 Kotlin 语法的类似 JavaScript 的构造,我推荐JSONKraken ,我是其中的作者。

Suggestions and opinions on the matter are much apreciated!非常感谢您对此事的建议和意见!

Kotin Seriazation科廷系列化

Kotlin specific library by Jetbrains for all supported platforms – Android, JVM, JavaScript, Native Jetbrains 的 Kotlin 特定库适用于所有支持的平台——Android、JVM、JavaScript、Native

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

Moshi莫希

Moshi is a JSON library for Android and Java by Square. Moshi 是 Square 的 Android 和 Java 的 JSON 库。

https://github.com/square/moshi https://github.com/square/moshi

Jackson杰克逊

https://github.com/FasterXML/jackson https://github.com/FasterXML/jackson

Gson格森

Most popular but almost deprecated最受欢迎但几乎已弃用

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

JSON to Java JSON 到 Java

http://www.jsonschema2pojo.org/ http://www.jsonschema2pojo.org/

JSON to Kotlin JSON 到 Kotlin

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

http://www.jsonschema2pojo.org/ Hi you can use this website to convert json to pojo. http://www.jsonschema2pojo.org/您好,您可以使用该网站将 json 转换为 pojo。
control+Alt+shift+k控制+Alt+Shift+k

After that you can manualy convert that model class to kotlin model class.之后,您可以将该模型类手动转换为 kotlin 模型类。 with the help of above shortcut.在上述快捷方式的帮助下。

Parse JSON string to Kotlin object将 JSON 字符串解析为 Kotlin 对象

As others recommend, Gson library is the simplest way!正如其他人所推荐的那样, Gson 库是最简单的方法!

If the File is in the Asset folder you can do like this, first add如果文件在Asset 文件夹中,您可以这样做,首先添加

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

then get a file from Asset :然后从Asset获取文件:

jsonString = context.assets.open(fileName).bufferedReader().use { it.readText() }

then use Gson :然后使用Gson

val gson = Gson()
val listPersonType = object : TypeToken<List<Person>>() {}.type
var persons: List<Person> = gson.fromJson(jsonFileString, listPersonType)
persons.forEachIndexed { idx, person -> Log.i("data", "> Item $idx:\n$person") }

Where Person is a Model/Data class , like this其中Person是一个Model/Data class ,像这样

data class Person(val name: String, val age: Int, val messages: List) {
}

Seems like Kotlin does not have any built-in method as in many cases it just imports and implements some tools from Java.似乎 Kotlin 没有任何内置方法,因为在许多情况下它只是从 Java 导入和实现一些工具。 After trying lots of packages, finally this one worked reasonably.在尝试了很多包之后,这个包终于可以正常工作了。 This fastjson from alibaba, which is very easy to use.这个来自阿里巴巴的fastjson,非常好用。 Inside build gradle dependencies:内部构建 gradle 依赖项:

implementation 'com.alibaba:fastjson:1.1.67.android'

Inside your Kotlin code:在您的 Kotlin 代码中:

import com.alibaba.fastjson.JSON
var jsonDecodedMap: Map<String, String> =
            JSON.parse(yourStringValueHere) as Map<String, String>;

i am using my custom implementation in kotlin:我在 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)
    }
}

You can use it like:你可以像这样使用它:

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

here is some useful links:这是一些有用的链接:

json parsing : json解析:

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

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

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

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

Download the source of deme from here( Json parsing in android kotlin )从这里下载 deme 的源代码( Json parsing in android kotlin

Add this dependency:添加此依赖项:

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

Call api function:调用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()

        }

    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM