【问题标题】:Accessing nested JSON [String: Any] object and appending to it访问嵌套的 JSON [String: Any] 对象并附加到它
【发布时间】:2019-07-02 11:56:03
【问题描述】:

使用 swift,我试图访问 JSON 的“locationConstraint”部分中的“locations”对象,如下所示:

        let jsonObj : [String: Any] =
            [
                "attendees": [
                    [
                        "type": "required",
                        "emailAddress": [
                            "name": nameOfRoom,
                            "address": roomEmailAddress
                        ]
                    ]
                ],
                "locationConstraint": [
                    "isRequired": "true",
                    "suggestLocation": "false",
                    "locations": [
                        [
                            "displayName": "First Floor Test Meeting Room 1",
                            "locationEmailAddress": "FirstFloorTestMeetingRoom1@onmicrosoft.com"
                        ],
                        [
                            "displayName": "Ground Floor Test Meeting Room 1",
                            "locationEmailAddress": "GroundFloorTestMeetingRoom1@onmicrosoft.com"
                        ]
                        //and the rest of the rooms below this.. 
                    ]
                ],
                "meetingDuration": durationOfMeeting,
        ]

我正在尝试从该方法之外向位置添加项目(以防止重复代码,因为位置列表可能很大) - 但我在替换回 json 的这一部分时遇到问题..

我的方法:

static func setupJsonObjectForFindMeetingTimeAllRoomsTest(nameOfRoom: String, roomEmailAddress: String, dateStartString: String, dateEndString: String, durationOfMeeting: String, locations: [String]) -> [String: Any] {
    let jsonObj : [String: Any] =
        [
            "attendees": [
                [
                    "type": "required",
                    "emailAddress": [
                        "name": nameOfRoom,
                        "address": roomEmailAddress
                    ]
                ]
            ],
            "meetingDuration": durationOfMeeting
    ]

    let jsonObject = addLocationsToExistingJson(locations:locations, jsonObj: jsonObj)
    return jsonObject
}

以及我将位置添加到现有 json 对象的方法:

static func addLocationsToExistingJson(locations: [String], jsonObj: [String: Any]) -> [String: Any] {
    var  data: [String: Any] = jsonObj

    let locConstraintObj = [
            "isRequired": "true",
            "suggestLocation": "false",
            "locations" : []

        ] as [String : Any]

    //try access locationConstraint part of json
    data["locationConstraint"] = locConstraintObj

    for i in stride(from: 0, to: locations.count, by: 1) {
        let item: [String: Any] =  [
            "displayName": locations[i],
            "locationEmailAddress": locations[i]
        ]

        // get existing items, or create new array if doesn't exist
        //this line below wrong? I need to access data["locationConstraint]["locations"]
        //but an error occurs when i change to the above.. .how do i access it?
        var existingItems = data["locations"] as? [[String: Any]] ?? [[String: Any]]()

        // append the item
        existingItems.append(item)

        // replace back into `data`
       data["locations"] = existingItems
    }
    return data
}

所以最终,我的最终 json 对象应该是这样的:

["meetingDuration": "PT60M", "returnSuggestionReasons": "true", “与会者”:[[“电子邮件地址”:[“地址”: “TestUser6@qubbook.onmicrosoft.com”、“名称”:“N”]、“类型”: "必需"]], "minimumAtendeePercentage": "100", "locationConstraint": ["locations": [["displayName": "一楼测试 会议室 1", "locationEmailAddress": "FirstFloorTestMeetingRoom1@qubbook.onmicrosoft.com"], ["displayName": “一楼测试会议室1”,“locationEmailAddress”: "GroundFloorTestMeetingRoom1@qubbook.onmicrosoft.com"]], “suggestLocation”:“false”,“isRequired”:“true”],“timeConstraint”: [“activityDomain”:“无限制”,“时隙”:[[“开始”: [“日期时间”:“2019-02-07 14:30:00”,“时区”:“UTC”],“结束”: ["dateTime": "2019-02-07 15:30:00", "timeZone": "UTC"]]]], "isOrganizerOptional": "true"]

它看起来像这样:

["timeConstraint": ["activityDomain": "unrestricted", "timeslots": [[“开始”:[“日期时间”:“2019-02-08 08:30:00”,“时区”:“UTC”], “结束”:[“日期时间”:“2019-02-08 09:30:00”,“时区”:“UTC”]]]], “locationConstraint”:[“suggestLocation”:“false”,“locations”:[], "isRequired": "true"], "attendees": [["emailAddress": ["address": “TestUser6@qubbook.onmicrosoft.com”、“名称”:“N”]、“类型”: "必需"]], "returnSuggestionReasons": "true", "isOrganizerOptional": "true", "minimumAtendeePercentage": "100", “位置”:[[“位置电子邮件地址”: "FirstFloorTestMeetingRoom1@qubbook.onmicrosoft.com", "displayName": "FirstFloorTestMeetingRoom1@qubbook.onmicrosoft.com"], [“位置电子邮件地址”: "GroundFloorTestMeetingRoom1@qubbook.onmicrosoft.com", "displayName": "GroundFloorTestMeetingRoom1@qubbook.onmicrosoft.com"]], "meetingDuration": "PT60M"]

在 JSON 的 locationConstraint 部分之外添加位置对象的位置。我知道我需要像这样访问我的 json 的 locationConstraint 部分:var existingItems = data["locationConstraint"]!["locations"] as? [[String: Any]] ?? [[String: Any]]() 但这会返回错误:

类型 'Any' 没有下标成员

这是我第一次使用 JSON 并尝试快速操作它们。我将如何解决这个问题?

【问题讨论】:

  • 我认为您应该关注Apple's advice 并从您的 JSON 创建一个模型对象,您会发现它更易于操作。使用泛型集合类来表示 DOM 总是很难使用,因此创建特定领域的类是值得的。
  • 我建议您不要创建 locationConstraint 数组,然后在发送数据之前附加其他参数。此外,您需要将 Any 类型转换为适当的格式,如数组或字典。
  • @Sachin Vas 你能告诉我你的意思吗?
  • 如果让位置 = data["locationConstraint]["locations"] as? [[String: Any]] { YOUR_CODE_HERE }
  • @Sachin Vas 它给了我错误:使用'?'链接可选仅对非“nil”基值和可选类型“Any?”的值访问成员“下标”必须解包以引用包装基类型'Any'的成员'下标'然后当我将其更改为 if let locations = data["locationConstraint"]?["locations"] as? [[String: Any]] { } 错误是:Type 'Any' 没有下标成员

标签: json swift dictionary


【解决方案1】:

使用模型对象和 Codable 的解决方案

正如 trojanfoe 建议的那样,您应该使用模型对象并直接操作它们。

import Foundation

struct Meeting: Codable {
    var attendees: [Attendee]
    var locationConstraint: LocationConstraint
    var meetingDuration: Int
}

struct Attendee: Codable {
    var type: Type
    var emailAddress: EmailAdress

    enum `Type`: String, Codable {
        case required
    }
}

struct LocationConstraint: Codable {
    var isRequired: Bool
    var suggestLocation: Bool
    var locations: [Location]
}

struct EmailAdress: Codable {
    var name: String
    var address: String
}

struct Location: Codable {
    var displayName: String
    var locationEmailAddress: String
}

首先我们拿你的字典...

let jsonDict: [String: Any] =
    [
        "attendees": [
            [
                "type": "required",
                "emailAddress": [
                    "name": "specificName",
                    "address": "specificAdress"
                ]
            ]
        ],
        "locationConstraint": [
            "isRequired": true,
            "suggestLocation": false,
            "locations": [
                [
                    "displayName": "First Floor Test Meeting Room 1",
                    "locationEmailAddress": "FirstFloorTestMeetingRoom1@onmicrosoft.com"
                ],
                [
                    "displayName": "Ground Floor Test Meeting Room 1",
                    "locationEmailAddress": "GroundFloorTestMeetingRoom1@onmicrosoft.com"
                ]
            ]
        ],
        "meetingDuration": 1800,
]

...并对其进行序列化。

let jsonData = try JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted)
print(String(data: jsonData, encoding: String.Encoding.utf8))

然后我们将其解码为我们的会议模型。

var meeting = try JSONDecoder().decode(Meeting.self, from: jsonData)

我们初始化一个新位置并将其附加到我们的 meeting.locationConstraints.locations 数组中。

let newLocation = Location(displayName: "newDisplayName", locationEmailAddress: "newLocationEmailAdress")
meeting.locationConstraint.locations.append(newLocation)

最后再次重新编码我们的模型对象。

let updatedJsonData = try JSONEncoder().encode(meeting)
print(String(data: updatedJsonData, encoding: String.Encoding.utf8))

【讨论】:

  • 感谢您的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-17
  • 1970-01-01
  • 2015-09-11
相关资源
最近更新 更多