我有一个JSONObject
我正在用来创建一个表。但是,当我第二次使用这些键创建每个单元格时,它什么也没做。我添加了日志语句来测试这一点。不key
打印单数 s。叫我难住了。
class MovieFragment : Fragment(), FinraDataInterface {
private lateinit var binding: MovieFragmentBinding
val finraDataInterface: FinraDataInterface = this
override fun drawTable(jsonArrayData: JSONArray) {
// ------ Draw the table -----
// Draw the keys first
val headerRow = TableRow(requireActivity())
Log.d("jsonArray", jsonArrayData[0].toString())
val firstRecord = jsonArrayData[0] as JSONObject
val keys = firstRecord.keys()
for (key in keys) {
val textView = TextView(requireActivity())
textView.text = key
headerRow.addView(textView)
}
binding.table.addView(headerRow)
// Draw the data second
for (i in 0 until jsonArrayData.length()) {
val record = jsonArrayData[i] as JSONObject
Log.d("Record", record.toString())
val tableRow = TableRow(requireActivity())
Log.d("Table Row", "Table Row created")
Log.d("Keys", listOf(keys).toString())
// Error is right here.
for (key in keys) {
Log.d("key", key)
val textView = TextView(requireActivity())
val cellText = record[key] as String
textView.text = cellText
tableRow.addView(textView)
}
binding.table.addView(tableRow)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = MovieFragmentBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
finraGetBondInfo("AMC")
}
private fun finraGetBondInfo(companyName: String) {
val url = "https://www.finra.org/finra-data/fixed-income/corp-and-agency"
val queue = Volley.newRequestQueue(requireActivity())
var cfruid = ""
val stringRequest = object: StringRequest(Request.Method.GET, url,
{ response ->
Log.d("A", "Response is: " + response.substring(0,500))
},
{ error ->
Log.e("Error", error.toString())
})
{
override fun parseNetworkResponse(response : NetworkResponse) : Response<String> {
// since we don't know which of the two underlying network vehicles
// will Volley use, we have to handle and store session cookies manually
Log.i("response", response.headers.toString());
val cookies = HttpCookie.parse(response.headers?.get("Set-Cookie"))
Log.d("Cookies:", cookies[0].toString())
val indexOfEqualSign = cookies[0].toString().indexOf('=')
cfruid = cookies[0].toString().substring(indexOfEqualSign + 1)
Log.d("Cfruid:", cfruid)
return super.parseNetworkResponse(response)
}
}
queue.add(stringRequest)
// Create our JSON Object for the finra call
val json = JSONObject()
val fieldsArray = JSONArray()
fieldsArray.put("issueSymbolIdentifier")
fieldsArray.put("issuerName")
fieldsArray.put("isCallable")
fieldsArray.put("productSubTypeCode")
fieldsArray.put("couponRate")
fieldsArray.put("maturityDate")
fieldsArray.put("industryGroup")
fieldsArray.put("moodysRating")
fieldsArray.put("standardAndPoorsRating")
fieldsArray.put("lastSalePrice")
fieldsArray.put("lastSaleYield")
json.put("fields", fieldsArray)
json.put("dateRangeFilters", JSONArray())
json.put("domainFilters", JSONArray())
json.put("compareFilters", JSONArray())
val multiJson = JSONObject()
multiJson.put("fuzzy", false)
multiJson.put("searchValue", companyName)
multiJson.put("synonym", true)
val subfieldsJson = JSONObject()
subfieldsJson.put("name", "issuerName")
subfieldsJson.put("boost", 1)
val fieldsArray2 = JSONArray()
fieldsArray2.put(subfieldsJson)
multiJson.put("fields", fieldsArray2)
val multiArray = JSONArray()
multiArray.put(multiJson)
json.put("multiFieldMatchFilters", multiArray)
json.put("orFilters", JSONArray())
json.put("aggregationFilter", JSONObject.NULL)
val sortFieldsArray = JSONArray()
sortFieldsArray.put("+issuerName")
json.put("sortFields", sortFieldsArray)
json.put("limit", 50)
json.put("offset", 0)
json.put("delimiter", JSONObject.NULL)
json.put("quoteValues", false)
Log.d("JSON", json.toString())
val url2 = "https://services-dynarep.ddwa.finra.org/public/reporting/v2/data/group/FixedIncomeMarket/name/CorporateAndAgencySecurities"
val request2 = object: JsonObjectRequest(Request.Method.POST, url2, json,
{ response ->
// TODO replace this with our calls to make tab2 display bond data
val returnBody = response["returnBody"] as JSONObject
var stringData = returnBody["data"] as String
stringData = stringData.replace("\\n", "").replace("\\", "")
val jsonArrayData = JSONArray(stringData)
finraDataInterface.drawTable(jsonArrayData)
},
{ error ->
Log.e("Error", error.toString())
})
{
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["Authority"] = "services-dynarep.ddwa.finra.org"
headers["Accept"] = "application/json, text/plain, */*"
headers["Cookie"] = "XSRF-TOKEN=$cfruid;"
headers["Origin"] = "https://www.finra.org"
headers["Referer"] = "https://www.finra.org/"
headers["X-XSRF-token"] = cfruid
headers["user-agent"] = "python-requests/2.31.0"
Log.d("headers:", headers.toString())
return headers
}
override fun getBodyContentType(): String {
return "application/json"
}
}
queue.add(request2)
}
}
让我特别困惑的是,使用键创建标题行的第一个 for 循环工作正常。我尝试将内容转换为不同的类型,看看是否存在某种类型错误。然而,这只是第二个 for 循环没有运行。我没有收到任何错误消息。我缺少什么?谢谢。
假设您在这里使用
JSON-java
(org.json
) 库,请注意JSONObject.keys()
方法返回一个Iterator
over 键。迭代器与集合不同Iterable
- 它是对某些数据的“实时”迭代,并且只能使用一次。在我们消耗完所有项目后,迭代器始终位于数据的末尾,并且不提供任何额外的项目。这很容易被忽视,因为大多数库不提供迭代器,而是提供可以多次使用的可迭代对象。
为了解决这个问题,我们需要使用创建另一个迭代器,
keys()
或者我们可以使用keySet()
,它返回一个集合,因此可以迭代多次。如果keySet()
不可用,我们可以使用以下命令将迭代器转换为列表asSequence().toList()
: