在被指出在 Swift 中使用 Codable 格式化 json 之后,我試圖將多個結果添加到 json 陣列中。不幸的是,我正在努力研究如何為包含多個屬性的一組結果構建這個 json 陣列。
這是我為兩個“組”結果所需的 json 陣列的示例(注意,記錄的資料中的組數可能會有所不同):
[{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"orientation_forward","value":"2"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"start_forward","value":"3.45"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"finish_forward","value":"5.29"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"minimum_forward","value":"7.81"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"maximum_forward","value":"9.20"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"1","field_name":"range_forward","value":"2.39"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"orientation_forward","value":"1"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"start_forward","value":"1.89"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"finish_forward","value":"4.20"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"minimum_forward","value":"8.26"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"maximum_forward","value":"46.82"},
{"record":"10","redcap_repeat_instrument":"range_of_motion_result","redcap_repeat_instance":"2","field_name":"range_forward","value":"2.98"}]
下面是我的 Swift 代碼。結果作為自定義型別陣列中的引數到達ORKRangeOfMotionResult(從ResearchKit每組結果中為我提供orientation、start、finish、minumum和屬性的值)maximum。range每組ORKRangeOfMotionResult還伴隨著一個識別符號 ( variableIdentifier),作為另一個結果,我可以使用它來確保我知道哪一組是哪一組。
我目前正在使用回圈來提取每個ORKRangeOfMotionResult屬性的單個值。[items]在此之后,使用variableIdentifierin陳述句將一個結果添加到 json 陣列相對容易if(如下所示start),但我不知道如何將一組結果中的所有屬性添加到陣列中。我猜是一個回圈,但還沒有弄清楚如何。
func buildJsonArrayOfResults(_ rangeOfMotionResults: [ORKRangeOfMotionResult], withIdentifier variableIdentifiers: [String]) {
let record = getIDNumber().stringValue
let repeat_instance = getRepeatInstance().stringValue
let repeat_instrument = "range_of_motion_result"
let event = getEventName()
var fieldName: String?
var identifier: String?
var stringData: String?
var value: String?
var items: [Item] = []
struct Item: Codable {
let record: String
let fieldName: String
let repeatInstance: String
let repeatInstrument: String
let value: String
let event: String
enum CodingKeys: String, CodingKey {
case record
case fieldName = "field_name"
case repeatInstance = "redcap_repeat_instance"
case repeatInstrument = "redcap_repeat_instrument"
case value
case event = "redcap_event_name"
}
}
var setNumber: Int = 0
while setNumber < rangeOfMotionResults.count {
setNumber = 1
// obtain results for each set of movements as a string
let orientation = String(rangeOfMotionResults[setNumber - 1].orientation)
let start = String(rangeOfMotionResults[setNumber - 1].start)
let finish = String(rangeOfMotionResults[setNumber - 1].finish)
let minimum = String(rangeOfMotionResults[setNumber - 1].minimum)
let maximum = String(rangeOfMotionResults[setNumber - 1].maximum)
let range = String(rangeOfMotionResults[setNumber - 1].range)
// assign one value and its redcap field name
identifier = variableIdentifiers[setNumber - 1]
if identifier!.contains("forward") {
fieldName = "start_forward"
value = start
} else if identifier!.contains("backward") {
fieldName = "start_backward"
value = start
} else if identifier!.contains("left.bending") {
fieldName = "start_left_bending"
value = start
} else if identifier!.contains("right.bending") {
fieldName = "start_right_bending"
value = start
} else if identifier!.contains("left.rotation") {
fieldName = "start_left_rotation"
value = start
} else if identifier!.contains("right.rotation") {
fieldName = "start_left_rotation"
value = start
}
let item = Item(record: record, fieldName: fieldName!, repeatInstance: String(repeat_instance), repeatInstrument: repeat_instrument, value: value!, event: event)
items.append(item)
}
do {
let data = try JSONEncoder().encode(items)
stringData = String(data: data, encoding: .utf8)
print(stringData!)
} catch {
print(error)
}
// now do something with stringData
}
所有的 hep 都欣然接受。先感謝您。
uj5u.com熱心網友回復:
根據給定的場景,您只需要這些屬性
func buildJsonArrayOfResults(_ rangeOfMotionResults: [ORKRangeOfMotionResult], withIdentifier variableIdentifiers: [String]) {
let record = getIDNumber().stringValue
let repeatInstance = getRepeatInstance().stringValue
let repeatInstrument = "range_of_motion_result"
let event = getEventName()
var items: [Item] = []
struct Item: Codable { ... }
由于識別符號的順序與結果陣列的順序相匹配,推薦的按索引和元素列舉陣列的方法是enumerated
for (index, result) in rangeOfMotionResults.enumerated() {
let identifier = variableIdentifiers[index]
似乎finish,minimum和maximum未range使用
// obtain results for each set of movements as a string
let orientation = String(result.orientation)
let value = String(result.start)
switch運算式比鏈條更快捷if - else
let fieldName : String
switch identifier {
case let id where id.contains("forward"): fieldName = "start_forward"
case let id where id.contains("backward"): fieldName = "start_backward"
case let id where id.contains("left.bending"): fieldName = "start_left_bending"
case let id where id.contains("right.bending"): fieldName = "start_right_bending"
case let id where id.contains("left.rotation"): fieldName = "start_left_rotation"
case let id where id.contains("right.rotation"): fieldName = "start_left_rotation"
default: fieldName = "unknown"
}
let item = Item(record: record, fieldName: fieldName, repeatInstance: repeatInstance, repeatInstrument: repeatInstrument, value: value, event: event)
items.append(item)
}
do {
let data = try JSONEncoder().encode(items)
let stringData = String(data: data, encoding: .utf8)!
print(stringData)
// now do something with stringData
} catch {
print(error)
}
}
for我還建議在回圈之前插入這一行
assert(rangeOfMotionResults.count == variableIdentifiers.count, "The size of rangeOfMotionResults and variableIdentifiers must be equal")
它檢查兩個陣列的大小是否相等,運算式在發布版本中被忽略。
uj5u.com熱心網友回復:
感謝@vadian 的回答,我能夠通過添加一個新struct的包含key-value pair一個識別符號(以及array這些“三重奏”中的一個)然后添加第二個for-in loop. 我確信我的代碼可以進一步優化(這會很有趣),但我很高興(也很感激)現在正在以我想要的方式構建 json 陣列。這是我的最終解決方案:
func buildJsonArrayOfResults(_ rangeOfMotionResults: [ORKRangeOfMotionResult], withIdentifier variableIdentifiers: [String]) {
let record = getIDNumber().stringValue
let repeatInstance = getRepeatInstance().stringValue
let repeatInstrument = "range_of_motion_result"
let event = getEventName()
var fieldName: String?
var identifier: String?
var stringData: String?
var value: String?
var items: [Item] = []
struct Item: Codable {
let record: String
let fieldName: String
let repeatInstance: String
let repeatInstrument: String
let value: String
let event: String
enum CodingKeys: String, CodingKey {
case record
case fieldName = "field_name"
case repeatInstance = "redcap_repeat_instance"
case repeatInstrument = "redcap_repeat_instrument"
case value
case event = "redcap_event_name"
}
}
struct Trio {
let key: String
let value: String
let identifier: String
}
var trios = [Trio]()
assert(rangeOfMotionResults.count == variableIdentifiers.count, "The size of rangeOfMotionResults and variableIdentifiers must be equal")
for (index, result) in rangeOfMotionResults.enumerated() {
identifier = variableIdentifiers[index]
// add key-value pairs with their identifiers to array
let orientation = String(result.orientation)
trios.append(Trio(key: "orientation", value: orientation, identifier: identifier!))
let start = String(result.start)
trios.append(Trio(key: "start", value: start, identifier: identifier!))
let finish = String(result.finish)
trios.append(Trio(key: "finish", value: finish, identifier: identifier!))
let minimum = String(result.minimum)
trios.append(Trio(key: "minimum", value: minimum, identifier: identifier!))
let maximum = String(result.maximum)
trios.append(Trio(key: "maximum", value: maximum, identifier: identifier!))
let range = String(result.range)
trios.append(Trio(key: "range", value: range, identifier: identifier!))
}
for (_, result) in trios.enumerated() {
let ident = result.identifier
value = result.value
let fieldName: String
switch ident {
case let id where id.contains("forward"):
fieldName = result.key "_forward"
case let id where id.contains("backward"):
fieldName = result.key "_backward"
case let id where id.contains("left.bending"):
fieldName = result.key "_left_bending"
case let id where id.contains("right.bending"):
fieldName = result.key "_right_bending"
case let id where id.contains("left.rotation"):
fieldName = result.key "_left_rotation"
case let id where id.contains("right.rotation"):
fieldName = result.key "_left_rotation"
default:
fieldName = result.key "_unknown"
}
let item = Item(record: record, fieldName: fieldName, repeatInstance: String(repeatInstance), repeatInstrument: repeatInstrument, value: value!, event: event)
items.append(item)
}
do {
let data = try JSONEncoder().encode(items)
stringData = String(data: data, encoding: .utf8)
print(stringData!)
// now do something with stringData
} catch {
print(error)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/422891.html
標籤:
上一篇:陣列中的陣列:jq:error(attest.json:91):object({"locations...)isnotvalidinacsvrow
