在Android中获取JSON对象 [英] Get json object in android
问题描述
我有文章视图,我的每个帖子都将显示详细信息(将其视为博客文章),但是我无法解析数据,因此我关闭了我的应用程序,而不是文章的详细信息.
I have article view where each post of mine will show details (think of it as blog post) but i cannot parse the data so i get my app closed instead of details of my articles.
ArticlesAdapter.kt
class ArticlesAdapter(val article : ArrayList<Article>) : RecyclerView.Adapter<ArticlesAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view: View =
LayoutInflater.from(parent.context).inflate(R.layout.fragment_articles, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return article.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = article.get(position).name
Glide.with(holder.aImage.context)
.load(article.get(position).image)
.placeholder(R.drawable.placeholder2)
.error(R.drawable.placeholder2)
.fallback(R.drawable.placeholder2) // if load was null
.into(holder.aImage)
Log.e("ImageURL", "URL = " + article.get(position).image)
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textView: TextView
var aImage: ImageView
init {
textView = itemView.findViewById(R.id.text_name)
aImage = itemView.findViewById(R.id.a_image)
}
}
}
ArticlesDetail.tk (my activity)
class ArticlesDetail : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.article_details)
callAPIDemo()
}
// api code
private fun callAPIDemo() {
val mySlugValue: String = intent.getStringExtra("my_slug")
Log.d("myslug in:", mySlugValue)
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(this)
val url = "https://example.com/api/articles/$mySlugValue"
// Request a string response from the provided URL.
val stringRequest = StringRequest(
Request.Method.GET, url,
Response.Listener<String> { response ->
val list: ArrayList<Article> = ArrayList()
getPosts(response,list)
// here you will have the complete list of data in your "list" variable
article_det.layoutManager = LinearLayoutManager(this)
Log.d("my list", list.toString())
article_det.adapter = ArticlesAdapter(list)
},
Response.ErrorListener { error ->
//displaying the error in toast if occurrs
Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT)
.show()
})
// Add the request to the RequestQueue.
queue.add(stringRequest)
}
fun getPosts(response: String,list:ArrayList<Article>) {
var jsonObject = JSONObject(response)
val jsonArray = jsonObject.getJSONArray("article")
for (i in 0 until jsonArray.length()) {
val jsonObject1 = jsonArray.getJSONObject(i)
var listingObject = Article(
jsonObject1.getInt("id"),
jsonObject1.getString("name"),
jsonObject1.getString("slug"),
jsonObject1.getString("image"),
jsonObject1.getString("body"),
jsonObject1.getString("icon"),
jsonObject1.getString("quote"),
jsonObject1.getString("video"),
jsonObject1.getString("user"),
jsonObject1.getString("created_at"),
jsonObject1.getString("updated_at")
)
list.add(listingObject)
}
}
}
Article.kt (my class)
data class Article (
val id: Int,
val name: String?,
val slug: String?,
val image: String?,
val body: String?,
val icon: String?,
val quote: String?,
val user: String?,
val video: String?,
val created_at: String?,
val updated_at: String?
)
然后对于视图,我有以下2个文件:
then for views i have this 2 files:
article_details.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/article_det"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
和fragment_articles.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<ImageView
android:id="@+id/a_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:contentDescription="@string/image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/a_image"
app:layout_constraintStart_toEndOf="@+id/a_image"
app:layout_constraintTop_toTopOf="@+id/a_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
很显然,最后一个xml文件将在以后进行编辑以获取更多信息 我的文章的详细信息,例如正文或用户等,但现在需要测试 返回的数据,我认为拥有文章的名称和图像就足够了.
Obviously this last xml file will be edited in future to get more details of my articles such as body or user etc. but for now to test returned data i think having name and image of article is enough.
数据
这是我在此活动中返回的数据的样子,
Data
this is how my returned data in this activity looks like,
Caused by: org.json.JSONException: No value for article
at org.json.JSONObject.get(JSONObject.java:392)
at org.json.JSONObject.getJSONArray(JSONObject.java:587)
at ui.ArticlesDetail.ArticlesDetail.getPosts(ArticlesDetail.kt:63)
at ui.ArticlesDetail.ArticlesDetail$callAPIDemo$stringRequest$1.onResponse(ArticlesDetail.kt:43)
at ui.ArticlesDetail.ArticlesDetail$callAPIDemo$stringRequest$1.onResponse(ArticlesDetail.kt:18)
我的第63行:val jsonArray = jsonObject.getJSONArray("article")
我的第43行:getPosts(response,list)
我的第18行:class ArticlesDetail : AppCompatActivity() {
- 任何想法,我的
callAPIDemo()
函数或getPosts()
的哪一部分 功能导致错误? - 我该如何解决?
- Any idea which part of my
callAPIDemo()
function orgetPosts()
function causing error? - how can I fix it?
更新
我的json数据:
Update
my json data:
{
"id": 4,
"user": "...",
"name": "...",
"slug": "...",
"image": "...",
"body": "...",
"icon": null,
"quote": null,
"video": null,
"categories": [
{
"id": 10,
"name": "...",
"slug": "...",
"icon": "..",
"body": "...",
"image": "...",
"created_at": "2019-11-23 05:35:31",
"updated_at": "2019-11-26 11:25:17"
}
],
"created_at": "2019-11-23 07:34:10",
"updated_at": "2019-11-23 07:37:52"
}
推荐答案
实际上,您的数组名称是类别,而不是文章
Actually the name of your Array is categories not article
因此在代码val jsonArray = jsonObject.getJSONArray("article")
的这一行中,您无需添加文章,而只需添加类别
so in this line of your code val jsonArray = jsonObject.getJSONArray("article")
, instead of article you need to add categories
类似下面的
val jsonArray = jsonObject.getJSONArray("categories")
-
如前所述,您的article_details.xml
将如下所示
As discussed your article_details.xml
will be like below
在这里您可以根据需要更改size
和margins
Here you can change size
and margins
, as you want
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/article_image"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="15dp"
android:maxLines="1"
android:text="userName"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/article_image" />
<TextView
android:id="@+id/article_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="5dp"
android:maxLines="1"
android:text="Article name"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<TextView
android:id="@+id/article_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. "
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/article_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在只需在ArticlesDetail
类中执行findfindViewById
,这样当您从API接收数据时就可以在它们上设置值
Now just do the findfindViewById
in your ArticlesDetail
class so you can set values on them when you receive data from your API
-
现在,您的ArticlesDetail
将类似于
class ArticlesDetail : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
var username: TextView? = null
var articleName: TextView? = null
var articleBody: TextView? = null
var articleImage: ImageView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
username = findViewById(R.id.username)
articleName = findViewById(R.id.article_name)
articleBody = findViewById(R.id.article_body)
articleImage = findViewById(R.id.article_image)
callAPIDemo()
}
// api code
private fun callAPIDemo() {
val mySlugValue: String = intent.getStringExtra("my_slug")
Log.d("myslug in:", mySlugValue)
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(this)
val url = "https://example.com/api/articles/$mySlugValue"
// Request a string response from the provided URL.
val stringRequest = StringRequest(
Request.Method.GET, url,
Response.Listener<String> { response ->
parseAndSetValues(response)
},
Response.ErrorListener { error ->
//displaying the error in toast if occurrs
Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT)
.show()
})
// Add the request to the RequestQueue.
queue.add(stringRequest)
}
private fun parseAndSetValues(response: String) {
val jsonObject = JSONObject(response)
username!!.text = jsonObject.getString("user")
articleName!!.text = jsonObject.getString("name")
articleBody!!.text = jsonObject.getString("body")
Glide.with(this).load(jsonObject.getString("image")).into(articleImage!!)
}
}
这篇关于在Android中获取JSON对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!