Kotlin - Как прочитать строку JSON на URL

Я новичок в Kotlin, и я нахожу библиотеку Klaxon для анализа JSON. Я не могу найти, как выполнить URL ( http://localhost:8080/items/2), прочитать строку JSON и сохранить данные в переменные и распечатать их в консоли. Создан и обновлен, мне не нужно сохранять.

JSON от URL:

{
    "brand": "Ferrero",
    "name": "Nutella",
    "healthy": false,
    "date": "2017-03-14T00:00:00.000Z",
    "id": 2,
    "createdAt": "2018-03-14T13:33:22.000Z",
    "updatedAt": "2018-03-20T21:23:44.000Z"
}

Код:

class DetailItem : AppCompatActivity()  {
    var itemId : String = ""
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_detail_item)
        itemId = intent.getStringExtra("itemId")
    }

    override fun onResume() {
        super.onResume()
        example()
    }

    private fun parse(name: String) : Any{
        val cls = Parser::class.java
        val inputStream = cls.getResourceAsStream(name)!!
        return Parser().parse(inputStream)!!
    }

    private fun example(){
        val url = "http://192.168.99.100:8080/items/" + itemId
        val obj = parse("url") as JsonObject

        val brand = obj.string("brand")
        val name = obj.string("name")
        println(brand + name)
    }

2 ответа

Решение

Проблема в том, что метод cls.getResourceAsStream(name) возвращается nullи !! Оператор вызывает выброс NPE.

Почему cls.getResourceAsStream(name) вернуть null? Это происходит потому, что метод getResourceAsStream ищет ресурс (то есть файл) с предоставленным name среди ресурсов, которые вы предоставляете в своем проекте.

Однако в вашем случае вы хотите загрузить JSON с URL-адреса, поэтому вам нужно сначала выполнить загрузку, которая даст вам JSON в форме String (или что-то, что может быть преобразовано в String), а затем проанализировать эту строку с Parser().parse(yourJsonString) as JsonObject,

РЕДАКТИРОВАТЬ

Вот пример, который использует библиотеку OkHttp:

import com.beust.klaxon.Klaxon
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException

fun main(args: Array<String>) {
    val url = "https://jsonplaceholder.typicode.com/posts/1"

    val client = OkHttpClient()
    val request = Request.Builder()
        .url(url)
        .build()

    println(Thread.currentThread())
    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call?, e: IOException?) {
            e?.printStackTrace()
        }

        override fun onResponse(call: Call?, response: Response) {
            if (!response.isSuccessful) {
                System.err.println("Response not successful")
                return
            }
            val json = response.body()!!.string()
            val myData = Klaxon().parse<MyData>(json)
            println("Data = $myData")
            println(Thread.currentThread())
        }

    })
    // Shutdown the executor as soon as the request is handled
    client.dispatcher().executorService().shutdown()
}

data class MyData(val title: String, val userId: Int)

Строка JSON, возвращаемая API REST:

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipitsuscipit recusandae consequuntur expedita et cumreprehenderit molestiae ut ut quas totamnostrum rerum est autem sunt rem eveniet architecto"
}

Этот код печатает:

Thread[main,5,main]
Data = MyData(title=sunt aut facere repellat provident occaecati excepturi optio reprehenderit, userId=1)
Thread[OkHttp https://jsonplaceholder.typicode.com/...,5,main]

Обратите внимание, что onResponse обратный вызов выполняется в рабочем потоке, а не в основном, поэтому, если вы используете этот код в Android, вы не сможете изменять элементы пользовательского интерфейса оттуда (если вы не используете runOnUiThread() или похожие методы)

Я нашел этот код, чтобы решить мою проблему. Но это AsyncTask, как его переписать и выполнить только когда захочу?

inner class AsyncTaskHandleJson : AsyncTask<String, String, String>() {
        override fun doInBackground(vararg url: String?): String {

            var text: String
            var connection = URL(url[0]).openConnection() as HttpURLConnection
            try {
                connection.connect()
                text = connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
            } finally {
                connection.disconnect()
            }

            return text
        }

        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)
            handleJson(result)
        }
    }

    private fun handleJson(jsonString: String?) {

        val jsonObject = JSONObject(jsonString)

        val itemIdBrand = findViewById<TextView>(R.id.itemIdBrand)
        itemIdBrand.text = jsonObject.getString("brand")

        println(jsonObject.getString("brand"))
    }
Другие вопросы по тегам