I am new to Kotlin and I find library Klaxon to parse JSON. I can not find how to execute url(http://localhost:8080/items/2), read JSON string and save data to variables and print them to console. CreatedAt and UpdatedAt I do not need to save.
JSON from 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"
}
Code:
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)
}
The issue is that method cls.getResourceAsStream(name)
returns null
, and the !!
operator causes the NPE to be thrown.
Why does cls.getResourceAsStream(name)
return null
? That happens because method getResourceAsStream
searches for a resource (i.e., file) with the provided name
among the resources you provide in your project.
In your case, however, you want to download the JSON from a URL, so you need to first perform the download, which will give you a JSON in form of String
(or something that can be converted to a String
), and then parse that string with Parser().parse(yourJsonString) as JsonObject
.
Here's an example that uses OkHttp library:
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)
The JSON string returned by the REST API is:
{
"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"
}
That code prints:
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]
Note that the onResponse
callback is executed on the worker thread and not on the main one, so if you use this code in Android, you won't be able to change UI elements from there (unless you use runOnUiThread()
or similar techniques)