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