swift - 在 Swift 中使用字符串路径访问结构变量
问题描述
我正在为 Swift 中的 JSON 表单构建一个自定义渲染器,以与用于我们基于 Web 的应用程序的 JSON 表单架构集成。如果你不熟悉,两个 JSON 文件用于生成 UI 表单组件并链接到后端。下面是 JSON Schema 和 JSON UI Schema 的示例,以及我从 JSON Schema 生成的 Person 结构。
范围值提供了一个字符串,可用于链接到后端人员数据的变量,但我很难弄清楚如何以可扩展的方式这样做。后端将是 Core Data 和(可能)SQLite(带有 SQLite.swift)的组合,但显示的结构将是从中提取数据的对象。我希望 Keypaths 会是这样,但我无法弄清楚如何直接从字符串生成 Keypath。我想我可以使用参考字典(字符串:Keypath),但这可能会与我们可能使用的后端失控。
在你问“为什么要这样做?”之前 答案是那是黄铜交给我的任务,所以……我必须!
JSON UI 架构:
{
"type": "VerticalLayout",
"elements": [
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/firstName"
},
{
"type": "Control",
"scope": "#/properties/lastName"
}
]
},
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/age"
},
{
"type": "Control",
"scope": "#/properties/dateOfBirth"
}
]
},
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/height"
},
{
"type": "Control",
"scope": "#/properties/gender"
},
{
"type": "Control",
"scope": "#/properties/committer"
}
]
},
{
"type": "Group",
"label": "Address for Shipping T-Shirt",
"elements": [
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/address/properties/street"
},
{
"type": "Control",
"scope": "#/properties/address/properties/streetnumber"
}
]
},
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/address/properties/postalCode"
},
{
"type": "Control",
"scope": "#/properties/address/properties/city"
}
]
}
],
"rule": {
"effect": "ENABLE",
"condition": {
"scope": "#/properties/committer",
"schema": {
"const": true
}
}
}
}
]
}
JSON模式:
{
"type": "person",
"required": [
"age"
],
"properties": {
"firstName": {
"type": "string",
"minLength": 2,
"maxLength": 20
},
"lastName": {
"type": "string",
"minLength": 5,
"maxLength": 15
},
"age": {
"type": "integer",
"minimum": 18,
"maximum": 100
},
"gender": {
"type": "string",
"enum": [
"Male",
"Female",
"Undisclosed"
]
},
"height": {
"type": "number"
},
"dateOfBirth": {
"type": "string",
"format": "date"
},
"rating": {
"type": "integer"
},
"committer": {
"type": "boolean"
},
"address": {
"type": "object",
"properties": {
"street": {
"type": "string"
},
"streetnumber": {
"type": "string"
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
}
}
}
}
}
人员结构:
struct Person: Storable {
var uuid: UUID = UUID()
var firstName: String?
var lastName: String?
var age: Int?
var gender: String?
var dateOfBirth: Date?
var height: Double?
var rating: Int?
var committer: Bool?
var address: Address?
}
struct Address: Storable {
var street: String?
var streetNumber: String?
var postalCode: String?
var city: String?
}
解决方案
如果它们不是 Objective-C 属性,则语言中没有任何内容可以支持这一点,因此您最终需要将字符串映射到键路径。
由于它基本上是样板代码,因此您可以使用 Sourcery 来生成映射,甚至可以使用可以解析 JSON 模式的东西来生成它。
推荐阅读
- java - com.android.ddmlib.InstallException:设备离线
- python - IndexError:循环时列表索引超出范围
- wordpress - .htaccess:重写规则以更改为语义 URL 结构
- sql-server - SSMS 18.4 覆盖具有相同用户名但不同服务器的密码
- vue.js - 如何修复导致网络错误的 nuxt js 静态站点链接?
- r - 如何将 xlsx 文件批量转换为 csv?
- javascript - Javascript - 带有速率限制器的进程内函数执行器?
- sql-server - 我可以在变量后命名表名的一部分吗?
- apache - Certbot - 更新您的客户端软件以继续使用 Let's Encrypt - 在 Ubuntu 14.04 中将 ACME v1 更新到 v2
- laravel - 如何增加会话 vue/cli 4.0.5 / vuex 3 / Laravel 6 Backend REST API app?