问题描述
我正在 Swift 中为 JSON 表单构建自定义渲染器,以与用于我们基于 Web 的应用程序的 JSON 表单架构集成。如果您不熟悉,可以使用两个 JSON 文件生成 UI 表单组件并链接到后端。下面是 JSON 架构和 JSON UI 架构的示例。 JSON 架构提供有关 UI 架构的数据类型的信息。然后为了将两者联系起来,范围提供了 JSON 模式中相关元素的路径。在一个极其简单的模式中,这还不错,但如果 JSON 中有很多嵌套,它就会变得有点愚蠢。我在下面有我的代码,用于通过将范围拆分为其组件然后挖掘字典来访问数据元素。有没有更好、更清洁、更少使用大锤的方法来做到这一点?我怀疑是否存在嵌套更深的数据的情况,但以防万一,只使用递归函数来查看每一层而不必自己进行操作会很好。我确定它存在,只是我没有看到。
在你问“为什么要这样做之前?”答案是那是黄铜交给我的任务,所以......我必须!
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"
}
}
}
}
}
JSON 用户界面架构:
{
"type": "VerticalLayout","elements": [
{
"type": "HorizontalLayout","elements": [
{
"type": "Control","scope": "#/properties/firstName"
},{
"type": "Control","scope": "#/properties/lastName"
}
]
},{
"type": "HorizontalLayout","scope": "#/properties/age"
},"scope": "#/properties/dateOfBirth"
}
]
},"scope": "#/properties/height"
},"scope": "#/properties/gender"
},"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","scope": "#/properties/address/properties/postalCode"
},"scope": "#/properties/address/properties/city"
}
]
}
],"rule": {
"effect": "ENABLE","condition": {
"scope": "#/properties/committer","schema": {
"const": true
}
}
}
}
]
}
static private func mapJSONSchemaToUISchema(_ uiSchema: JSONUISchemaElement)->JSONSchemaElement? {
guard let scope = uiSchema.scope else {
return nil
}
// separate out the scope string into components by /,starts with #,then properties,then the name of the JSONSchema element,then if it's nested,it will repeat properties and JSONSchemaElement,with the last element always being the element we would want. There's a more elegant way to do this,however,this is the brute force for Now.
let scopeComponentPath = scope.components(separatedBy: "/")
if scopeComponentPath.count < 3 {
return nil
} else {
let element = getJSONElementFromPath(scopeComponentPath)
return element
}
}
//iterrates through the JSON Schema to find the correct element based on the path (parsed from the UI Scope) to return the JSON Schema element,even if it's nested up to 5 layers deep. If we continue to nest beyond 5 layers,this will require addressing.
static private func getJSONElementFromPath(_ stringsPath: [String]) ->JSONSchemaElement? {
print(stringsPath)
switch stringsPath.count {
case 3:
// not nested
return jsonSchemaRootElement.properties?[stringsPath[2]]
case 5:
// nested in first level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]
case 7:
// nested in second level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]?.properties?[stringsPath[6]]
case 9:
// nested in third level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]?.properties?[stringsPath[6]]?.properties?[stringsPath[8]]
case 11:
// nested in fourth level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]?.properties?[stringsPath[6]]?.properties?[stringsPath[8]]?.properties?[stringsPath[10]]
case 13:
// nested in fifth level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]?.properties?[stringsPath[6]]?.properties?[stringsPath[8]]?.properties?[stringsPath[10]]?.properties?[stringsPath[12]]
case 15:
// nested in sixth level object
return jsonSchemaRootElement.properties?[stringsPath[2]]?.properties?[stringsPath[4]]?.properties?[stringsPath[6]]?.properties?[stringsPath[8]]?.properties?[stringsPath[10]]?.properties?[stringsPath[12]]?.properties?[stringsPath[14]]
default:
print("no elements found in personjsONSchema array")
return nil
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)