首页 > 解决方案 > 转换为 JSON

问题描述

我正在通过从苹果的 healthkit 访问健康数据来开发一个健康应用程序。我可以访问血压和 BMI 数据。

我希望以 JSON 格式将此数据发送回我的 JS 文件。

所需的格式是这样的

{   "items" : [
    {
      "endDate" : "2020-01-25",
      "BloodPressure" : "122/65",
      "startDate" : "2020-01-25"
    },
    {
      "endDate" : "2020-01-25",
      "BMI" : "24.6",
      "startDate" : "2020-01-25"
    }   ] }

我的 BP 和 BMI 查询是:

func getBloodPressure(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    var value : Any = ""
    guard let type = HKQuantityType.correlationType(forIdentifier: HKCorrelationTypeIdentifier.bloodPressure),
                let systolicType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureSystolic),
                let diastolicType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bloodPressureDiastolic) else {

                    return
            }
         let now = Date()
         let startDate = Calendar.current.startOfDay(for: now)
         let endDate = now
         let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)

            let sampleQuery = HKSampleQuery(sampleType: type, predicate: predicate, limit: 0, sortDescriptors: nil) { (sampleQuery, results, error) in
                if let dataList = results as? [HKCorrelation] {
                    for data in dataList
                    {
                        if let data1 = data.objects(for: systolicType).first as? HKQuantitySample,
                            let data2 = data.objects(for: diastolicType).first as? HKQuantitySample {

                            let value1 = data1.quantity.doubleValue(for: HKUnit.millimeterOfMercury())
                            let value2 = data2.quantity.doubleValue(for: HKUnit.millimeterOfMercury())
                            value = "\(value1) / \(value2)"
                            resolve(value)
                        }}}}
                   healthStore.execute(sampleQuery)
      }

 @objc
  func getBMI(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    let bodyMassType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex)
    let query = HKSampleQuery(sampleType: bodyMassType!, predicate: nil, limit: 1, sortDescriptors: nil) { (query, results, error) in
                if let result = results?.first as? HKQuantitySample {
                  let bodyMassIndex = result.quantity.doubleValue(for: HKUnit.count())
                    print("BMI in xcode",bodyMassIndex, result.endDate)
                  resolve(bodyMassIndex)
                    return
                }}
       healthStore.execute(query)
      }

现在我创建了 2 个结构:

struct BloodPressureItem: Codable {
        let endDate: String?
        let BloodPressure: String?
        let startDate: String?
    }

struct BodyMassIndexItem: Codable {
        let endDate: String?
        let BMI: String?
        let startDate: String?
    }

接下来,我将对象附加到我的数据中。

let jsonData = BloodPressureItem.init(endDate: end, Bloodpressure: String(value), startDate: start)
let jsonData = BodyMassIndexItem.init(endDate: end, BMI: String(bodyMassIndex), startDate: start)

我得到的结果是

BloodPressureItem(endDate: Optional("2021-01-25 07:43:27 +0000"), BloodPressure: Optional("122.0/65.0"), startDate: Optional("2021-01-24 07:43:27 +0000"))

BodyMassIndexItem(endDate: Optional("2021-01-25 07:43:27 +0000"), BMI: Optional("24.6"), startDate: Optional("2021-01-24 07:43:27 +0000"))

接下来如何将其转换为我需要的格式?

更新:

{   "items" : [
    “BloodPressure:” {
      "endDate" : "2020-01-25",
      “Value” : "122/65",
      "startDate" : "2020-01-25"
    },
   “BMI:” {
      "endDate" : "2020-01-25",
      “Value” : "24.6",
      "startDate" : "2020-01-25"
    }   ] }

标签: iosjsonswift

解决方案


创建包含其他两个的第三个结构

struct HealthData: Codable {
    let bloodPressure: BloodPressureItem
    let bmi: BodyMassIndexItem
}

然后编码这个结构的一个实例

let bloodPressure = BloodPressureItem.init(endDate: end, Bloodpressure: String(value), startDate: start)
let bmi = BodyMassIndexItem(endDate: end, BMI: String(bodyMassIndex), startDate: start)

let healthData = HealthData(bloodPressure: bloodPressureItem, bmi: bmiItem)

do {
    let data = try JSONEncoder().encode(healthData)
} catch { 
     //error handling
}

我假设您要发送其中一个,否则您可以简单地将属性更改为数组,

struct HealthData: Codable {
    let bloodPressureValues: [BloodPressureItem]
    let bmiValues: [BodyMassIndexItem]
}

在您的代码中,您已将所有内容设为可选并且类型为 String,我建议不要使用可选的,而是使用原始类型,例如

struct BloodPressureItem: Codable {
    let endDate: Date
    let BloodPressure: Double
    let startDate: Date
}

另一种可能的解决方案是对所有类型的数据使用单个自定义类型

enum HealthDataType: String, Codable {
    case bloodPressure
    case bmi
}
struct HealtDataItem: Codable {
    let endDate: Date
    let value: Double
    let startDate: Date
    let type: HealthDataType
}

然后将所有对象添加到数组中并对数组进行编码

let bloodPressureItem = HealtDataItem(endDate: end, value: bloodPressureValue, startDate: start, type: .bloodPressure)
let bmiItem = HealtDataItem(endDate: end, value: bmiValue, startDate: start, type: .bmi)

let healthData = [bloodPressureItem, bmiItem]

do {
    let data = try JSONEncoder().encode(healthData)
} catch { 
     //error handling
}

推荐阅读