有没有更好的方法可以使用 get 从带有 swift 路径的子词典中获取项目?

问题描述

我正在 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...